mirror of
https://github.com/joohoi/acme-dns.git
synced 2024-12-22 21:33:51 +07:00
116 lines
3.5 KiB
Go
116 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/kataras/iris"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Serve is an authentication middlware function used to authenticate update requests
|
|
func (a authMiddleware) Serve(ctx iris.Context) {
|
|
allowUpdate := false
|
|
usernameStr := ctx.GetHeader("X-Api-User")
|
|
password := ctx.GetHeader("X-Api-Key")
|
|
postData := ACMETxt{}
|
|
|
|
username, err := getValidUsername(usernameStr)
|
|
if err == nil && validKey(password) {
|
|
au, err := DB.GetByUsername(username)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{"error": err.Error()}).Error("Error while trying to get user")
|
|
// To protect against timed side channel (never gonna give you up)
|
|
correctPassword(password, "$2a$10$8JEFVNYYhLoBysjAxe2yBuXrkDojBQBkVpXEQgyQyjn43SvJ4vL36")
|
|
} else {
|
|
if correctPassword(password, au.Password) {
|
|
// Password ok
|
|
|
|
// Now test for the possibly limited ranges
|
|
if DNSConf.API.UseHeader {
|
|
ips := getIPListFromHeader(ctx.GetHeader(DNSConf.API.HeaderName))
|
|
allowUpdate = au.allowedFromList(ips)
|
|
} else {
|
|
allowUpdate = au.allowedFrom(ctx.RemoteAddr())
|
|
}
|
|
|
|
if allowUpdate {
|
|
// Update is allowed from remote addr
|
|
if err := ctx.ReadJSON(&postData); err == nil {
|
|
if au.Subdomain == postData.Subdomain {
|
|
ctx.Next()
|
|
return
|
|
}
|
|
} else {
|
|
// JSON error
|
|
log.WithFields(log.Fields{"error": err.Error()}).Warning("Failed reading POST data")
|
|
ctx.JSON(iris.Map{"error": "bad data"})
|
|
ctx.StatusCode(iris.StatusBadRequest)
|
|
return
|
|
}
|
|
}
|
|
} else {
|
|
// Wrong password
|
|
log.WithFields(log.Fields{"username": username}).Warning("Failed password check")
|
|
}
|
|
}
|
|
}
|
|
ctx.JSON(iris.Map{"error": "unauthorized"})
|
|
ctx.StatusCode(iris.StatusUnauthorized)
|
|
}
|
|
|
|
func webRegisterPost(ctx iris.Context) {
|
|
var regJSON iris.Map
|
|
var regStatus int
|
|
aTXT := ACMETxt{}
|
|
_ = ctx.ReadJSON(&aTXT)
|
|
// Create new user
|
|
nu, err := DB.Register(aTXT.AllowFrom)
|
|
if err != nil {
|
|
errstr := fmt.Sprintf("%v", err)
|
|
regJSON = iris.Map{"error": errstr}
|
|
regStatus = iris.StatusInternalServerError
|
|
log.WithFields(log.Fields{"error": err.Error()}).Debug("Error in registration")
|
|
} else {
|
|
regJSON = iris.Map{"username": nu.Username, "password": nu.Password, "fulldomain": nu.Subdomain + "." + DNSConf.General.Domain, "subdomain": nu.Subdomain, "allowfrom": nu.AllowFrom.ValidEntries()}
|
|
regStatus = iris.StatusCreated
|
|
|
|
log.WithFields(log.Fields{"user": nu.Username.String()}).Debug("Created new user")
|
|
}
|
|
ctx.JSON(regJSON)
|
|
ctx.StatusCode(regStatus)
|
|
}
|
|
|
|
func webUpdatePost(ctx iris.Context) {
|
|
// User auth done in middleware
|
|
a := ACMETxt{}
|
|
userStr := ctx.GetHeader("X-API-User")
|
|
// Already checked in auth middlware
|
|
username, _ := getValidUsername(userStr)
|
|
// Already checked in auth middleware
|
|
_ = ctx.ReadJSON(&a)
|
|
a.Username = username
|
|
// Do update
|
|
if validSubdomain(a.Subdomain) && validTXT(a.Value) {
|
|
err := DB.Update(a)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{"error": err.Error()}).Debug("Error while trying to update record")
|
|
webUpdatePostError(ctx, errors.New("internal error"), iris.StatusInternalServerError)
|
|
return
|
|
}
|
|
ctx.JSON(iris.Map{"txt": a.Value})
|
|
ctx.StatusCode(iris.StatusOK)
|
|
} else {
|
|
log.WithFields(log.Fields{"subdomain": a.Subdomain, "txt": a.Value}).Debug("Bad data for subdomain")
|
|
webUpdatePostError(ctx, errors.New("bad data"), iris.StatusBadRequest)
|
|
return
|
|
}
|
|
}
|
|
|
|
func webUpdatePostError(ctx iris.Context, err error, status int) {
|
|
errStr := fmt.Sprintf("%v", err)
|
|
updJSON := iris.Map{"error": errStr}
|
|
ctx.JSON(updJSON)
|
|
ctx.StatusCode(status)
|
|
}
|