Skip to content

Commit

Permalink
Feature/tls support (#35)
Browse files Browse the repository at this point in the history
* Added support for binding server to a specific interface using new parameter "ip"
* Added support for TLS/HTTPS using new parameters "tlscertfile" and "tlskeyfile"
* Panic if "mediapath" and "cachepath" equals
  • Loading branch information
midstar committed Jun 9, 2020
1 parent d275330 commit b26d9be
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 20 deletions.
5 changes: 4 additions & 1 deletion FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ Yes, MediaWEB only allows read access of media files whithin your media folder.
* Access non-media files within your media folder
* Access any file outside of your media folder

If you protect your content using a username and password (enable in mediaweb.conf) you should enable TLS/HTTPS (separate server as proxy is currently needed), otherwise it would be possible to sniff the network for your username and password.
If you protect your content using a username and password (enable in mediaweb.conf) you should enable TLS/HTTPS,
otherwise it would be possible to sniff the network for your username and password.

See [README](README.md) for how to enable authentication and TLS/HTTPS.

## How do I view my media?

Expand Down
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ Interface suited for mobile devices
* Thumbnail support for images and videos, primary by reading of EXIF thumbnail if it exist, otherwise thumbnails will be created and stored in a thumbnail cache. Video thumbnails requires [ffmpeg](https://www.ffmpeg.org/) to be installed
* Automatic rotation JPEG images when needed (based on EXIF information)
* Generate thumbnails on the fly, on start-up and/or when new files are added to the media directory
* **NEW!** Automatically resize images to reduce network bandwidth and get a smoother navigation at client
* Automatically resize images to reduce network bandwidth and get a smoother navigation at client
* Optional authentication with username and password
* **NEW!** Support for both HTTP and encryption using HTTPS (TLS)

## Download and install Linux

Expand Down Expand Up @@ -250,10 +251,27 @@ out with the *cachepath* has enough disk space.
Also, if you have many images and are running on an SBC it might take very, very long
time the first time the images are resized. Count with several days.

### Enable encryption with TLS (HTTPS) and password protection

## Future improvements
By default MediaWEB will use the standard open HTTP protocol without
any authentication. If you decide to add authentication you should
always enable encryption using TLS (HTTPS). If you don't do this
it would be possible to sniff the network and get your user name
and password.

* Add support for TLS/SSL
username = myusername
password = mypassword
tlscertfile = public.crt
tlskeyfile = private.key

OpenSSL can be used to generate the public and private key:

openssl genrsa -out private.key 2048
openssl req -new -x509 -sha256 -key private.key -out public.crt -days 3650

The above key is self signed, which basically means that your browser
won't trust it by default, but you can always ignore the warnings
in your browser. The link will still be secure.


## Author and license
Expand Down
21 changes: 21 additions & 0 deletions configs/example.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDYDCCAkigAwIBAgIJANn5CV2NXnnlMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAlNFMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMjAwNjA3MTgzNDI3WhcNMzAwNjA1MTgzNDI3WjBF
MQswCQYDVQQGEwJTRTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAxE1tZNyhjLUBH19LcALeYUpi3WVLVAvXh/ohXftVvJIpKgbM2l6xeAFD
+N5dR+N3qcgUm4cQZ2jJPx9vpAeIQZT6siH2ySaMUp7UQE8Kt9t6GH5x6mC7nShG
+clLE3AKJaG5TyyNccHIX9dAt3wlYWho8L76kXFOn2+v2hBKUy7Vyhn27hJlDBOY
iCWj5WkrcF/6mEmKUtxY1NTe+BpkCNddMVtXsFH5GC6XV/4x83KhnJak7IRPGn1e
ueiu3KbCafwJXHbgZWBIkfVmdnDUGYQvyeKrAiLkAqvNrV3zl8FRrW+k8LBHVbEa
zyDfHW3VxG+6IGLX+S9Q+l4vgeZGxwIDAQABo1MwUTAdBgNVHQ4EFgQUsBZUbZN+
3Bx+XylnZw7bT8f3ruIwHwYDVR0jBBgwFoAUsBZUbZN+3Bx+XylnZw7bT8f3ruIw
DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAbZx9ns6EFEnv5cXL
K1fj6WG0Oq9w5MFWElaNOTtNcTop1lFuat2fl2TWgsR/FK9u/13IZWqRGTmE97AZ
WGyk9sRl6kF0ilApeiofTzJmDQ00VH06h6ouZgvd41TkVeLrC3WRVynizGIiGmXD
G2pvVocLfS9wRCRabvvkHQbJxrOAW8OEqvb9Xy4YVTS7NnkvW6ZUarSfrNsJBf5w
HO6OI8+py+a41sH8wugg31L8cDvo3uCoPSPocjU7kJtmNaWjSDkT1cXWWm5P4zKG
qMprN/4CvZBkJukrd77h7Aj7szuJdoDwMqi48BARtfnkGDMf1CbraN2KdFcwpg1d
hJCgtA==
-----END CERTIFICATE-----
27 changes: 27 additions & 0 deletions configs/example.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAxE1tZNyhjLUBH19LcALeYUpi3WVLVAvXh/ohXftVvJIpKgbM
2l6xeAFD+N5dR+N3qcgUm4cQZ2jJPx9vpAeIQZT6siH2ySaMUp7UQE8Kt9t6GH5x
6mC7nShG+clLE3AKJaG5TyyNccHIX9dAt3wlYWho8L76kXFOn2+v2hBKUy7Vyhn2
7hJlDBOYiCWj5WkrcF/6mEmKUtxY1NTe+BpkCNddMVtXsFH5GC6XV/4x83KhnJak
7IRPGn1eueiu3KbCafwJXHbgZWBIkfVmdnDUGYQvyeKrAiLkAqvNrV3zl8FRrW+k
8LBHVbEazyDfHW3VxG+6IGLX+S9Q+l4vgeZGxwIDAQABAoIBAFkF6Bt6t0TRfV3V
4Kc+lc03Z9iRrHTEHg2LkQBHEB3BhyuJA/PwR7ltkX7WkSUd8lGr7DSQLw9GhSW8
Quv3goKDZqHMJ1gXxEFfyFAVyH2S6i8bgNvS3KKr9mwnLoX1JJTmX9yZDthNEmrs
emv7wBQJvrWXVpkI8qf5hZ12D87ivjpZPiTgET9l9Iz8tGaT+0DU5gMx7V9XuVxB
5vGGZOl/AROVhste1ZRCY84r4+A9xksKjPPwjTTE+2KJWDpOmIgZsjipXQ2dRMbQ
hUHVMt8DozLa28RlKUDmMQ/raeXZrmsyswMRziM1NgWxrRfXLWAWPbXmMvpPDp/k
MCze3ukCgYEA4eFjx1N6RRyZ3hM5dT7k6LJ+qqCMhndrsJjSLw9uWXkNaEfi6NOG
Q/xj/aQIAy0mqKEFJ6ku0StBNvcFY9mcwq9GJ2OUIR/yPHM0e6Bl+zbt9V+MlB2c
8w4AwwJZEdFU6HyzMrkGUUQInZqaPjDLFBHoLqTMuEgao2Ip0YUGAnsCgYEA3npe
lUI38i9670ZbK/GCtABdruMTQaxrIUDdwEDlhglIO75shHUPBZvkBtbJ1OsHCN4R
kjlSH3E8aZJ08sL3GAWX//p0+t4m59S8WgG3mdMEmVTLKG1tAiOXHn7GvwSBEEiT
vLv5/KQTMvDg6GuJBI+sl86wjQa9udxLn3MNUSUCgYAXOgj7jx7simNcDZgD8WKy
duBFhVrN3OvK7fv28NxFAQia54FytYWB6isSAtL8GKF4B46zJFd3FL6Q+1eni9Ht
xv4swLWTrmhHRQVpjPXPnjdb2uZmuKDR8Wespcoo5eCYQ3Jdzd7Tbm6AXkxsBrJr
Lug0G6gdbvSmRkrMi6QxjwKBgDubf7Hv7vtle0OWjyDj8Uf2/SK5VlR3NLDRJ1i2
Soix/fd72qlWj7LKBLtMWwFAAz99+Ck8UGN6PFxw0AKm9/sorIP5/9OjJ7tfhSN8
aEu/fPD0BgaL4vP6wyd5ghh1xXquZ17e4mitMTOp1CiRf0GImQ6HY0g1sSmV+3D6
K2w9AoGAeIhCMXA8+k7fB/89keUNxODlAY+edk8H/IW0pnX0ljXdOt+XguImcFxE
V3/PM6FtHNFV0TWM3YSl3Ot6iPuM2+IF1gNVuxDvgGzhoiCQOivpL9UB+PwweoOq
gPIzosENPxsC2oeaMwJkPXTD2VUX/wJl6j+dNIETWfrlJjqPDIU=
-----END RSA PRIVATE KEY-----
22 changes: 20 additions & 2 deletions configs/mediaweb.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
# This parameter is MANDATORY
port = 9834

# Network inteface to listen to.
# If parameter is not set, the server will listen to
# all interfaces.
#ip = 127.0.0.1

# Media path, i.e. where is your media located
# This parameter is MANADTORY
#
Expand All @@ -18,9 +23,11 @@ mediapath = pictures
# temp folder + mediaweb. Cache path is where
# thumbnails and preview images are stored.
#
# Is not allowed to be the same as mediapath.
#
# For example:
# mediapath = /home/fobar/cache/mediaweb
# mediapath = c:\users\fobar\cache\mediaweb
# cachepath = /home/fobar/cache/mediaweb
# cachepath = c:\users\fobar\cache\mediaweb
#cachepath = tmpcache

# Thumb cache is by default on. Uncomment below to
Expand Down Expand Up @@ -87,3 +94,14 @@ mediapath = pictures
#username = myusername
#password = mypassword

# User name and password for authentication. Leave commented
# for no authentication
#username = myusername
#password = mypassword

# TLS (HTTPS) certification file and key file. Leave commented
# for no encryption (HTTP). If both parameters are set TlS
# will be enabled.
#tlscertfile = public.crt
#tlskeyfile = private.key

3 changes: 2 additions & 1 deletion main_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func mainCommon() *WebAPI {
s.enableThumbCache, s.genThumbsOnStartup,
s.genThumbsOnAdd, s.autoRotate, s.enablePreview, s.previewMaxSide,
s.genPreviewOnStartup, s.genPreviewOnAdd)
webAPI := CreateWebAPI(s.port, "templates", media, box, s.userName, s.password)
webAPI := CreateWebAPI(s.port, s.ip, "templates", media, box,
s.userName, s.password, s.tlsCertFile, s.tlsKeyFile)
return webAPI
}
17 changes: 15 additions & 2 deletions mediaweb.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
# This parameter is MANDATORY
port = 9834

# Network inteface to listen to.
# If parameter is not set, the server will listen to
# all interfaces.
#ip = 127.0.0.1

# Media path, i.e. where is your media located
# This parameter is MANADTORY
#
Expand All @@ -18,9 +23,11 @@ mediapath = testmedia
# temp folder + mediaweb. Cache path is where
# thumbnails and preview images are stored.
#
# Is not allowed to be the same as mediapath.
#
# For example:
# mediapath = /home/fobar/cache/mediaweb
# mediapath = c:\users\fobar\cache\mediaweb
# cachepath = /home/fobar/cache/mediaweb
# cachepath = c:\users\fobar\cache\mediaweb
cachepath = tmpcache

# Thumb cache is by default on. Uncomment below to
Expand Down Expand Up @@ -86,3 +93,9 @@ cachepath = tmpcache
#username = myusername
#password = mypassword

# TLS (HTTPS) certification file and key file. Leave commented
# for no encryption (HTTP). If both parameters are set TlS
# will be enabled.
#tlscertfile = public.crt
#tlskeyfile = private.key

15 changes: 15 additions & 0 deletions scripts/windows_installer.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,21 @@ Section "${APPLICATION_NAME}" SectionMain
FileWrite $4 "# This parameter is MANDATORY$\r$\n"
FileWrite $4 "port = 9834$\r$\n"
FileWrite $4 "$\r$\n"
FileWrite $4 "# Network inteface to listen to.$\r$\n"
FileWrite $4 "# If parameter is not set, the server will listen to$\r$\n"
FileWrite $4 "# all interfaces.$\r$\n"
FileWrite $4 "#ip = 127.0.0.1$\r$\n"
FileWrite $4 "$\r$\n"
FileWrite $4 "# Media path, i.e. where is your media located$\r$\n"
FileWrite $4 "# This parameter is MANADTORY$\r$\n"
FileWrite $4 "mediapath = $0$\r$\n"
FileWrite $4 "$\r$\n"
FileWrite $4 "# Cache path is by default your operating systems$\r$\n"
FileWrite $4 "# temp folder + mediaweb. Cache path is where$\r$\n"
FileWrite $4 "# thumbnails and preview images are stored.$\r$\n"
FileWrite $4 "#$\r$\n"
FileWrite $4 "# Is not allowed to be the same as mediapath.$\r$\n"
FileWrite $4 "#$\r$\n"
FileWrite $4 "#cachepath =$\r$\n"
FileWrite $4 "$\r$\n"
FileWrite $4 "# Thumbnail cache is on by default$\r$\n"
Expand Down Expand Up @@ -242,6 +250,13 @@ Section "${APPLICATION_NAME}" SectionMain
FileWrite $4 "# for no authentication$\r$\n"
FileWrite $4 "#username = myusername$\r$\n"
FileWrite $4 "#password = mypassword$\r$\n"
FileWrite $4 "$\r$\n"
FileWrite $4 "# TLS (HTTPS) certification file and key file. Leave commented\r$\n"
FileWrite $4 "# for no encryption (HTTP). If both parameters are set TlS\r$\n"
FileWrite $4 "# will be enabled.\r$\n"
FileWrite $4 "#tlscertfile = public.crt\r$\n"
FileWrite $4 "#tlskeyfile = private.key\r$\n"
FileWrite $4 "$\r$\n"

FileClose $4

Expand Down
31 changes: 31 additions & 0 deletions settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

type settings struct {
port int // Network port
ip string // Network IP ("" means any)
mediaPath string // Top level path for media files
cachePath string // Top level path for cache (thumbs and preview)
enableThumbCache bool // Generate thumbnails
Expand All @@ -25,6 +26,8 @@ type settings struct {
logFile string // Log file ("" means stderr)
userName string // User name ("" means no authentication)
password string // Password
tlsCertFile string // TLS certification file
tlsKeyFile string // TLS key file
}

// defaultConfPath holds configuration file paths in priority order
Expand Down Expand Up @@ -69,6 +72,11 @@ func loadSettings(fileName string) settings {
}
result.port = port

// Load IP (OPTIONAL)
// Default: ""
ip := config.GetString("ip", "")
result.ip = ip

// Load mediaPath (MANDATORY)
if !config.HasKey("mediapath") {
llog.Panic("Mandatory property 'mediapath' is not defined in %s", fileName)
Expand All @@ -93,6 +101,11 @@ func loadSettings(fileName string) settings {
}
}

// Check that mediapath and cachepath are not the same
if pathEquals(result.mediaPath, result.cachePath) {
llog.Panic("cachepath and mediapath have the same value '%s'", result.mediaPath)
}

// Load enableThumbCache (OPTIONAL)
// Default: true
enableThumbCache, err := config.GetBool("enablethumbcache", true)
Expand Down Expand Up @@ -177,6 +190,16 @@ func loadSettings(fileName string) settings {
password := config.GetString("password", "")
result.password = password

// Load tlsCertFile (OPTIONAL)
// Default: ""
tlsCertFile := config.GetString("tlscertfile", "")
result.tlsCertFile = tlsCertFile

// Load tlsKeyFile (OPTIONAL)
// Default: ""
tlsKeyFile := config.GetString("tlskeyfile", "")
result.tlsKeyFile = tlsKeyFile

return result
}

Expand All @@ -202,3 +225,11 @@ func toLogLvl(level string) llog.Level {

return logLevel
}

func pathEquals(path1, path2 string) bool {
diffPath, err := filepath.Rel(path1, path2)
if err == nil && (diffPath == "" || diffPath == ".") {
return true
}
return false
}
33 changes: 33 additions & 0 deletions settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,17 @@ mediapath = Y:\pictures`
assertEqualsStr(t, "logFile", "", s.logFile)
assertEqualsStr(t, "userName", "", s.userName)
assertEqualsStr(t, "password", "", s.password)
assertEqualsStr(t, "ip", "", s.ip)
assertEqualsStr(t, "tlsCertFile", "", s.tlsCertFile)
assertEqualsStr(t, "tlsKeyFile", "", s.tlsKeyFile)

}

func TestSettings(t *testing.T) {
contents :=
`
port = 80
ip = 192.168.1.2
mediapath = /media/usb/pictures
cachepath = /tmp/thumb
enablethumbcache = off
Expand All @@ -56,6 +60,8 @@ loglevel = debug
logfile = /tmp/log/mediaweb.log
username = an_email@password.com
password = A!#_q7*+
tlscertfile = /file/my_cert_file.crt
tlskeyfile = /file/my_cert_file.key
`
fullPath := createConfigFile(t, "TestSettings.conf", contents)
s := loadSettings(fullPath)
Expand All @@ -78,6 +84,9 @@ password = A!#_q7*+
assertEqualsStr(t, "logFile", "/tmp/log/mediaweb.log", s.logFile)
assertEqualsStr(t, "userName", "an_email@password.com", s.userName)
assertEqualsStr(t, "password", "A!#_q7*+", s.password)
assertEqualsStr(t, "ip", "192.168.1.2", s.ip)
assertEqualsStr(t, "tlsCertFile", "/file/my_cert_file.crt", s.tlsCertFile)
assertEqualsStr(t, "tlsKeyFile", "/file/my_cert_file.key", s.tlsKeyFile)

}

Expand Down Expand Up @@ -235,3 +244,27 @@ func TestFindConfFileMissing(t *testing.T) {
findConfFile() // Shall panic
t.Fatalf("Should have paniced here")
}


func TestPathEquals(t *testing.T) {
assertTrue(t, "", pathEquals("adir", "adir"))
assertTrue(t, "", pathEquals("adir/anotherdir", "adir/anotherdir"))
assertTrue(t, "", pathEquals("adir/anotherdir", "adir/anotherdir/third/.."))

assertFalse(t, "", pathEquals("adir", "bdir"))
assertFalse(t, "", pathEquals("sameroot/leaf1", "sameroot/leaf2"))
assertFalse(t, "", pathEquals("root1/leaf1", "root2/leaf1"))
assertFalse(t, "", pathEquals("/unix/u", "C:\\windows\\w"))
}

func TestSettingsSameMediaAndCachePath(t *testing.T) {
contents :=
`
port = 80
mediapath = Y:\pictures
cachepath = Y:\pictures`
fullPath := createConfigFile(t, "TestSettingsSameMediaAndCachePath.conf", contents)
defer expectPanic(t)
loadSettings(fullPath)
t.Fatal("Panic expected")
}

0 comments on commit b26d9be

Please sign in to comment.