Skip to content
Merged
4 changes: 4 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ PASSWORD_HASH_ALGO = argon2
CSRF_COOKIE_HTTP_ONLY = true
; Validate against https://haveibeenpwned.com/Passwords to see if a password has been exposed
PASSWORD_CHECK_PWN = false
; Use a camo image proxy - leave empty to not use
CAMO_SERVER_URL =
; HMAC to encode urls with
CAMO_HMAC_KEY =

[openid]
;
Expand Down
2 changes: 2 additions & 0 deletions docs/content/doc/advanced/config-cheat-sheet.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ set name for unique queues. Individual queues will default to
- spec - use one or more special characters as ``!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~``
- off - do not check password complexity
- `PASSWORD_CHECK_PWN`: **false**: Check [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) to see if a password has been exposed.
- `CAMO_SERVER_URL`: **<empty>**: If you would like to use a camo proxy to proxy images from rendered content, set the camo server url here
- `CAMO_HMAC_KEY`: **<empty>**: Provide the HMAC key for encoding urls

## OpenID (`openid`)

Expand Down
35 changes: 35 additions & 0 deletions modules/markup/camo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package markup

import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"strings"

"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)

// CamoEncode encodes a lnk to fit with the go-camo and camo proxy links
func CamoEncode(link []byte) []byte {
if bytes.HasPrefix(link, []byte(setting.CamoServerURL)) || len(setting.CamoHMACKey) == 0 {
return link
}

hmacKey := []byte(setting.CamoHMACKey)
mac := hmac.New(sha1.New, hmacKey)
_, _ = mac.Write(link) // hmac does not return errors
macSum := b64encode(mac.Sum(nil))
encodedURL := b64encode(link)

return []byte(util.URLJoin(setting.CamoServerURL, macSum, encodedURL))
}

func b64encode(data []byte) string {
return strings.TrimRight(base64.URLEncoding.EncodeToString(data), "=")
}
9 changes: 9 additions & 0 deletions modules/markup/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,17 @@ func (ctx *postProcessCtx) visitNode(node *html.Node, visitText bool) {

lnk := string(link)
lnk = util.URLJoin(prefix, lnk)

link = []byte(lnk)
}
if setting.CamoServerURL != "" {
lnk := string(link)
lnkURL, _ := url.Parse(lnk)
if lnkURL.IsAbs() && !strings.HasPrefix(lnk, setting.AppURL) {
// We should camo this url
link = CamoEncode(link)
}
}
node.Attr[idx].Val = string(link)
}
} else if node.Data == "a" {
Expand Down
4 changes: 4 additions & 0 deletions modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ var (
PasswordComplexity []string
PasswordHashAlgo string
PasswordCheckPwn bool
CamoServerURL string
CamoHMACKey string

// UI settings
UI = struct {
Expand Down Expand Up @@ -746,6 +748,8 @@ func NewContext() {
PasswordHashAlgo = sec.Key("PASSWORD_HASH_ALGO").MustString("argon2")
CSRFCookieHTTPOnly = sec.Key("CSRF_COOKIE_HTTP_ONLY").MustBool(true)
PasswordCheckPwn = sec.Key("PASSWORD_CHECK_PWN").MustBool(false)
CamoServerURL = sec.Key("CAMO_SERVER_URL").MustString("")
CamoHMACKey = sec.Key("CAMO_HMAC_KEY").MustString("")

InternalToken = loadInternalToken(sec)

Expand Down