Fixes security issue & Adds support to sent configuration via email (#83)

This commit is contained in:
Georgios Komninos 2021-08-08 20:55:59 +03:00 committed by GitHub
parent 7edcd1b80c
commit 1711530dda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 335 additions and 76 deletions

View file

@ -1,6 +1,7 @@
package handler
import (
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
@ -13,6 +14,7 @@ import (
"github.com/labstack/echo-contrib/session"
"github.com/labstack/echo/v4"
"github.com/labstack/gommon/log"
"github.com/ngoduykhanh/wireguard-ui/emailer"
"github.com/ngoduykhanh/wireguard-ui/model"
"github.com/ngoduykhanh/wireguard-ui/util"
"github.com/rs/xid"
@ -77,8 +79,6 @@ func Logout() echo.HandlerFunc {
// WireGuardClients handler
func WireGuardClients() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
clientDataList, err := util.GetClients(true)
if err != nil {
@ -97,8 +97,6 @@ func WireGuardClients() echo.HandlerFunc {
// GetClients handler return a list of Wireguard client data
func GetClients() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
clientDataList, err := util.GetClients(true)
if err != nil {
@ -114,8 +112,6 @@ func GetClients() echo.HandlerFunc {
// GetClient handler return a of Wireguard client data
func GetClient() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
clientID := c.Param("id")
clientData, err := util.GetClientByID(clientID, true)
@ -130,8 +126,6 @@ func GetClient() echo.HandlerFunc {
// NewClient handler
func NewClient() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
client := new(model.Client)
c.Bind(client)
@ -194,11 +188,53 @@ func NewClient() echo.HandlerFunc {
}
}
// EmailClient handler to sent the configuration via email
func EmailClient(mailer emailer.Emailer, emailSubject, emailContent string) echo.HandlerFunc {
type clientIdEmailPayload struct {
ID string `json:"id"`
Email string `json:"email"`
}
return func(c echo.Context) error {
var payload clientIdEmailPayload
c.Bind(&payload)
// TODO validate email
clientData, err := util.GetClientByID(payload.ID, true)
if err != nil {
log.Errorf("Cannot generate client id %s config file for downloading: %v", payload.ID, err)
return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"})
}
// build config
server, _ := util.GetServer()
globalSettings, _ := util.GetGlobalSettings()
config := util.BuildClientConfig(*clientData.Client, server, globalSettings)
cfg_att := emailer.Attachment{"wg0.conf", []byte(config)}
qrdata, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(clientData.QRCode, "data:image/png;base64,"))
if err != nil {
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "decoding: " + err.Error()})
}
qr_att := emailer.Attachment{"wg.png", qrdata}
err = mailer.Send(
clientData.Client.Name,
payload.Email,
emailSubject,
emailContent,
[]emailer.Attachment{cfg_att, qr_att},
)
if err != nil {
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, err.Error()})
}
return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Email sent successfully"})
}
}
// UpdateClient handler to update client information
func UpdateClient() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
_client := new(model.Client)
c.Bind(_client)
@ -257,8 +293,6 @@ func UpdateClient() echo.HandlerFunc {
// SetClientStatus handler to enable / disable a client
func SetClientStatus() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
data := make(map[string]interface{})
err := json.NewDecoder(c.Request().Body).Decode(&data)
@ -320,8 +354,6 @@ func DownloadClient() echo.HandlerFunc {
// RemoveClient handler
func RemoveClient() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
client := new(model.Client)
c.Bind(client)
@ -346,8 +378,6 @@ func RemoveClient() echo.HandlerFunc {
// WireGuardServer handler
func WireGuardServer() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
server, err := util.GetServer()
if err != nil {
@ -365,8 +395,6 @@ func WireGuardServer() echo.HandlerFunc {
// WireGuardServerInterfaces handler
func WireGuardServerInterfaces() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
serverInterface := new(model.ServerInterface)
c.Bind(serverInterface)
@ -396,8 +424,6 @@ func WireGuardServerInterfaces() echo.HandlerFunc {
// WireGuardServerKeyPair handler to generate private and public keys
func WireGuardServerKeyPair() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
// gen Wireguard key pair
key, err := wgtypes.GeneratePrivateKey()
@ -428,8 +454,6 @@ func WireGuardServerKeyPair() echo.HandlerFunc {
// GlobalSettings handler
func GlobalSettings() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
globalSettings, err := util.GetGlobalSettings()
if err != nil {
@ -446,8 +470,6 @@ func GlobalSettings() echo.HandlerFunc {
// GlobalSettingSubmit handler to update the global settings
func GlobalSettingSubmit() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
globalSettings := new(model.GlobalSetting)
c.Bind(globalSettings)
@ -477,8 +499,6 @@ func GlobalSettingSubmit() echo.HandlerFunc {
// MachineIPAddresses handler to get local interface ip addresses
func MachineIPAddresses() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
// get private ip addresses
interfaceList, err := util.GetInterfaceIPs()
@ -503,8 +523,6 @@ func MachineIPAddresses() echo.HandlerFunc {
// SuggestIPAllocation handler to get the list of ip address for client
func SuggestIPAllocation() echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
server, err := util.GetServer()
if err != nil {
@ -541,8 +559,6 @@ func SuggestIPAllocation() echo.HandlerFunc {
// ApplyServerConfig handler to write config file and restart Wireguard server
func ApplyServerConfig(tmplBox *rice.Box) echo.HandlerFunc {
return func(c echo.Context) error {
// access validation
validSession(c)
server, err := util.GetServer()
if err != nil {

View file

@ -9,22 +9,32 @@ import (
"github.com/ngoduykhanh/wireguard-ui/util"
)
// validSession to redirect user to the login page if they are not authenticated or session expired.
func validSession(c echo.Context) {
if !util.DisableLogin {
sess, _ := session.Get("session", c)
cookie, err := c.Cookie("session_token")
if err != nil || sess.Values["session_token"] != cookie.Value {
func ValidSession(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if !isValidSession(c) {
nextURL := c.Request().URL
if nextURL != nil {
c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/login?next=%s", c.Request().URL))
if nextURL != nil && c.Request().Method == http.MethodGet {
return c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/login?next=%s", c.Request().URL))
} else {
c.Redirect(http.StatusTemporaryRedirect, "/login")
return c.Redirect(http.StatusTemporaryRedirect, "/login")
}
}
return next(c)
}
}
func isValidSession(c echo.Context) bool {
if util.DisableLogin {
return true
}
sess, _ := session.Get("session", c)
cookie, err := c.Cookie("session_token")
if err != nil || sess.Values["session_token"] != cookie.Value {
return false
}
return true
}
// currentUser to get username of logged in user
func currentUser(c echo.Context) string {
if util.DisableLogin {