2016-11-11 16:48:00 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2016-11-13 14:50:44 +02:00
|
|
|
"crypto/rand"
|
2018-08-12 19:48:39 +03:00
|
|
|
"errors"
|
2017-11-14 23:54:29 +02:00
|
|
|
"fmt"
|
2016-11-13 14:50:44 +02:00
|
|
|
"math/big"
|
2017-11-14 00:42:30 +02:00
|
|
|
"os"
|
2016-11-11 16:48:00 +02:00
|
|
|
"regexp"
|
2016-11-13 14:50:44 +02:00
|
|
|
"strings"
|
2016-12-02 17:04:16 +02:00
|
|
|
|
|
|
|
"github.com/BurntSushi/toml"
|
2017-11-14 00:42:30 +02:00
|
|
|
log "github.com/sirupsen/logrus"
|
2016-11-11 16:48:00 +02:00
|
|
|
)
|
|
|
|
|
2017-11-14 23:54:29 +02:00
|
|
|
func jsonError(message string) []byte {
|
|
|
|
return []byte(fmt.Sprintf("{\"error\": \"%s\"}", message))
|
|
|
|
}
|
|
|
|
|
2018-08-12 18:49:17 +03:00
|
|
|
func fileIsAccessible(fname string) bool {
|
2017-11-14 00:42:30 +02:00
|
|
|
_, err := os.Stat(fname)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
2018-08-12 18:49:17 +03:00
|
|
|
f, err := os.Open(fname)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
f.Close()
|
2017-11-14 00:42:30 +02:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-08-12 18:49:17 +03:00
|
|
|
func readConfig(fname string) (DNSConfig, error) {
|
2016-11-16 19:15:36 +02:00
|
|
|
var conf DNSConfig
|
2018-08-12 18:49:17 +03:00
|
|
|
_, err := toml.DecodeFile(fname, &conf)
|
2018-08-12 19:48:39 +03:00
|
|
|
if err != nil {
|
|
|
|
// Return with config file parsing errors from toml package
|
|
|
|
return conf, err
|
|
|
|
}
|
|
|
|
return prepareConfig(conf)
|
|
|
|
}
|
|
|
|
|
|
|
|
// prepareConfig checks that mandatory values exist, and can be used to set default values in the future
|
|
|
|
func prepareConfig(conf DNSConfig) (DNSConfig, error) {
|
|
|
|
if conf.Database.Engine == "" {
|
|
|
|
return conf, errors.New("missing database configuration option \"engine\"")
|
|
|
|
}
|
|
|
|
if conf.Database.Connection == "" {
|
|
|
|
return conf, errors.New("missing database configuration option \"connection\"")
|
|
|
|
}
|
2018-08-12 20:19:58 +03:00
|
|
|
|
|
|
|
// Default values for options added to config to keep backwards compatibility with old config
|
|
|
|
if conf.API.ACMECacheDir == "" {
|
|
|
|
conf.API.ACMECacheDir = "api-certs"
|
|
|
|
}
|
|
|
|
|
2018-08-12 19:48:39 +03:00
|
|
|
return conf, nil
|
2016-11-16 15:31:40 +02:00
|
|
|
}
|
|
|
|
|
2016-11-23 17:11:31 +02:00
|
|
|
func sanitizeString(s string) string {
|
2016-11-13 14:50:44 +02:00
|
|
|
// URL safe base64 alphabet without padding as defined in ACME
|
2021-01-11 17:31:09 +02:00
|
|
|
re, _ := regexp.Compile(`[^A-Za-z\-\_0-9]+`)
|
2016-11-13 14:50:44 +02:00
|
|
|
return re.ReplaceAllString(s, "")
|
|
|
|
}
|
|
|
|
|
2018-03-15 00:23:55 +02:00
|
|
|
func sanitizeIPv6addr(s string) string {
|
|
|
|
// Remove brackets from IPv6 addresses, net.ParseCIDR needs this
|
2021-01-11 17:31:09 +02:00
|
|
|
re, _ := regexp.Compile(`[\[\]]+`)
|
2018-03-15 00:23:55 +02:00
|
|
|
return re.ReplaceAllString(s, "")
|
|
|
|
}
|
|
|
|
|
2016-11-27 21:21:38 +02:00
|
|
|
func generatePassword(length int) string {
|
2016-11-13 14:50:44 +02:00
|
|
|
ret := make([]byte, length)
|
|
|
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_"
|
|
|
|
alphalen := big.NewInt(int64(len(alphabet)))
|
|
|
|
for i := 0; i < length; i++ {
|
2016-11-27 21:21:38 +02:00
|
|
|
c, _ := rand.Int(rand.Reader, alphalen)
|
2016-11-13 14:50:44 +02:00
|
|
|
r := int(c.Int64())
|
|
|
|
ret[i] = alphabet[r]
|
|
|
|
}
|
2016-11-27 21:21:38 +02:00
|
|
|
return string(ret)
|
2016-11-13 14:50:44 +02:00
|
|
|
}
|
|
|
|
|
2016-11-23 17:11:31 +02:00
|
|
|
func sanitizeDomainQuestion(d string) string {
|
2016-11-27 19:41:54 +02:00
|
|
|
dom := strings.ToLower(d)
|
|
|
|
firstDot := strings.Index(d, ".")
|
|
|
|
if firstDot > 0 {
|
|
|
|
dom = dom[0:firstDot]
|
2016-11-13 14:50:44 +02:00
|
|
|
}
|
|
|
|
return dom
|
|
|
|
}
|
|
|
|
|
2016-11-27 21:21:38 +02:00
|
|
|
func setupLogging(format string, level string) {
|
2016-11-27 23:21:46 +02:00
|
|
|
if format == "json" {
|
2016-11-26 15:42:35 +02:00
|
|
|
log.SetFormatter(&log.JSONFormatter{})
|
2016-11-23 17:11:31 +02:00
|
|
|
}
|
2016-11-27 22:09:13 +02:00
|
|
|
switch level {
|
2016-11-23 17:11:31 +02:00
|
|
|
default:
|
2016-11-26 15:42:35 +02:00
|
|
|
log.SetLevel(log.WarnLevel)
|
|
|
|
case "debug":
|
|
|
|
log.SetLevel(log.DebugLevel)
|
2016-11-23 17:11:31 +02:00
|
|
|
case "info":
|
2016-11-26 15:42:35 +02:00
|
|
|
log.SetLevel(log.InfoLevel)
|
|
|
|
case "error":
|
|
|
|
log.SetLevel(log.ErrorLevel)
|
2016-11-23 17:11:31 +02:00
|
|
|
}
|
2016-11-26 15:42:35 +02:00
|
|
|
// TODO: file logging
|
2016-11-23 17:11:31 +02:00
|
|
|
}
|
2016-11-27 21:21:38 +02:00
|
|
|
|
2016-12-02 17:04:16 +02:00
|
|
|
func getIPListFromHeader(header string) []string {
|
|
|
|
iplist := []string{}
|
|
|
|
for _, v := range strings.Split(header, ",") {
|
|
|
|
if len(v) > 0 {
|
|
|
|
// Ignore empty values
|
|
|
|
iplist = append(iplist, strings.TrimSpace(v))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return iplist
|
|
|
|
}
|