feat: vendor gitea 1.16.2

This commit is contained in:
2026-06-02 08:36:01 +00:00
parent 247cd60f69
commit 54798b4615
2145 changed files with 162965 additions and 126447 deletions
@@ -9,7 +9,6 @@ import (
"errors"
"fmt"
net_mail "net/mail"
"regexp"
"strings"
"time"
@@ -21,34 +20,13 @@ import (
"github.com/dimiro1/reply"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/jhillyerd/enmime"
)
var (
addressTokenRegex *regexp.Regexp
referenceTokenRegex *regexp.Regexp
"github.com/jhillyerd/enmime/v2"
)
func Init(ctx context.Context) error {
if !setting.IncomingEmail.Enabled {
return nil
}
var err error
addressTokenRegex, err = regexp.Compile(
fmt.Sprintf(
`\A%s\z`,
strings.Replace(regexp.QuoteMeta(setting.IncomingEmail.ReplyToAddress), regexp.QuoteMeta(setting.IncomingEmail.TokenPlaceholder), "(.+)", 1),
),
)
if err != nil {
return err
}
referenceTokenRegex, err = regexp.Compile(fmt.Sprintf(`\Areply-(.+)@%s\z`, regexp.QuoteMeta(setting.Domain)))
if err != nil {
return err
}
go func() {
ctx, _, finished := process.GetManager().AddTypedContext(ctx, "Incoming Email", process.SystemProcessType, true)
defer finished()
@@ -241,7 +219,7 @@ loop:
return nil
}
handlerType, user, payload, err := token.ExtractToken(ctx, t)
handlerType, user, payload, err := token.DecodeToken(ctx, t)
if err != nil {
if _, ok := err.(*token.ErrToken); ok {
log.Info("Invalid incoming email token: %v", err)
@@ -292,22 +270,31 @@ func isAutomaticReply(env *enmime.Envelope) bool {
return autoRespond != ""
}
func extractToken(s, tokenPrefix, tokenSuffix string) string {
if len(s) <= len(tokenPrefix)+len(tokenSuffix) {
return ""
}
prefix, suffix := s[0:len(tokenPrefix)], s[len(s)-len(tokenSuffix):]
if strings.EqualFold(prefix, tokenPrefix) && strings.EqualFold(suffix, tokenSuffix) {
return s[len(tokenPrefix) : len(s)-len(tokenSuffix)]
}
return ""
}
// searchTokenInHeaders looks for the token in To, Delivered-To and References
func searchTokenInHeaders(env *enmime.Envelope) string {
if addressTokenRegex != nil {
to, _ := env.AddressList("To")
to, _ := env.AddressList("To")
token := searchTokenInAddresses(to)
if token != "" {
return token
}
token := searchTokenInAddresses(to)
if token != "" {
return token
}
deliveredTo, _ := env.AddressList("Delivered-To")
deliveredTo, _ := env.AddressList("Delivered-To")
token = searchTokenInAddresses(deliveredTo)
if token != "" {
return token
}
token = searchTokenInAddresses(deliveredTo)
if token != "" {
return token
}
references := env.GetHeader("References")
@@ -322,10 +309,9 @@ func searchTokenInHeaders(env *enmime.Envelope) string {
if end == -1 || begin > end {
break
}
match := referenceTokenRegex.FindStringSubmatch(references[begin:end])
if len(match) == 2 {
return match[1]
t := extractToken(references[begin:end], "reply-", "@"+setting.Domain)
if t != "" {
return t
}
references = references[end+1:]
@@ -336,15 +322,15 @@ func searchTokenInHeaders(env *enmime.Envelope) string {
// searchTokenInAddresses looks for the token in an address
func searchTokenInAddresses(addresses []*net_mail.Address) string {
for _, address := range addresses {
match := addressTokenRegex.FindStringSubmatch(address.Address)
if len(match) != 2 {
continue
}
return match[1]
tokenPrefix, tokenSuffix, _ := strings.Cut(setting.IncomingEmail.ReplyToAddress, setting.IncomingEmailTokenPlaceholder)
if tokenSuffix == "" {
return ""
}
for _, address := range addresses {
if t := extractToken(address.Address, tokenPrefix, tokenSuffix); t != "" {
return t
}
}
return ""
}
@@ -67,7 +67,7 @@ func (h *ReplyHandler) Handle(ctx context.Context, content *MailContent, doer *u
return err
}
perm, err := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
perm, err := access_model.GetDoerRepoPermission(ctx, issue.Repo, doer)
if err != nil {
return err
}
@@ -88,7 +88,7 @@ func (h *ReplyHandler) Handle(ctx context.Context, content *MailContent, doer *u
for _, attachment := range content.Attachments {
attachmentBuf := bytes.NewReader(attachment.Content)
uploaderFile := attachment_service.NewLimitedUploaderKnownSize(attachmentBuf, attachmentBuf.Size())
a, err := attachment_service.UploadAttachmentGeneralSizeLimit(ctx, uploaderFile, setting.Attachment.AllowedTypes, &repo_model.Attachment{
a, err := attachment_service.UploadAttachmentForIssue(ctx, uploaderFile, &repo_model.Attachment{
Name: attachment.Name,
UploaderID: doer.ID,
RepoID: issue.Repo.ID,
@@ -171,7 +171,7 @@ func (h *UnsubscribeHandler) Handle(ctx context.Context, _ *MailContent, doer *u
return err
}
perm, err := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
perm, err := access_model.GetDoerRepoPermission(ctx, issue.Repo, doer)
if err != nil {
return err
}
@@ -7,7 +7,9 @@ import (
"strings"
"testing"
"github.com/jhillyerd/enmime"
"code.gitea.io/gitea/modules/setting"
"github.com/jhillyerd/enmime/v2"
"github.com/stretchr/testify/assert"
)
@@ -68,6 +70,18 @@ func TestIsAutomaticReply(t *testing.T) {
}
}
func TestSearchTokenInHeadersCaseInsensitive(t *testing.T) {
setting.IncomingEmail.ReplyToAddress = "InComing+%{token}@ExAmPle.com"
setting.Domain = "DoMain.com"
mkEnv := func(s string) *enmime.Envelope {
env, _ := enmime.ReadEnvelope(strings.NewReader(s + "\r\n\r\n"))
return env
}
assert.Equal(t, "abc", searchTokenInHeaders(mkEnv("To: incoming+abc@EXAMPLE.COM")))
assert.Equal(t, "abc", searchTokenInHeaders(mkEnv("Delivered-To: INCOMING+abc@example.com")))
assert.Equal(t, "abc", searchTokenInHeaders(mkEnv("References: <ReplY-abc@DomaiN.COM>")))
}
func TestGetContentFromMailReader(t *testing.T) {
mailString := "Content-Type: multipart/mixed; boundary=message-boundary\r\n" +
"\r\n" +
+11 -9
View File
@@ -15,7 +15,6 @@ import (
"mime"
"regexp"
"strings"
"sync/atomic"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
@@ -32,12 +31,10 @@ import (
const mailMaxSubjectRunes = 256 // There's no actual limit for subject in RFC 5322
var loadedTemplates atomic.Pointer[templates.MailTemplates]
var subjectRemoveSpaces = regexp.MustCompile(`[\s]+`)
func LoadedTemplates() *templates.MailTemplates {
return loadedTemplates.Load()
func LoadedTemplates() *templates.MailRender {
return templates.MailRenderer()
}
// SendTestMail sends a test mail
@@ -161,18 +158,23 @@ func (b64embedder *mailAttachmentBase64Embedder) AttachmentSrcToBase64DataURI(ct
func fromDisplayName(u *user_model.User) string {
if setting.MailService.FromDisplayNameFormatTemplate != nil {
var ctx bytes.Buffer
err := setting.MailService.FromDisplayNameFormatTemplate.Execute(&ctx, map[string]any{
var buf bytes.Buffer
err := setting.MailService.FromDisplayNameFormatTemplate.Execute(&buf, map[string]any{
"DisplayName": u.DisplayName(),
"AppName": setting.AppName,
"Domain": setting.Domain,
})
if err == nil {
return mime.QEncoding.Encode("utf-8", ctx.String())
return mime.QEncoding.Encode("utf-8", buf.String())
}
log.Error("fromDisplayName: %w", err)
}
return u.GetCompleteName()
def := u.Name
if fullName := strings.TrimSpace(u.FullName); fullName != "" {
// use "Full Name (username)" for email's sender name if Full Name is not empty
def = fullName + " (" + u.Name + ")"
}
return def
}
func generateMetadataHeaders(repo *repo_model.Repository) map[string]string {
@@ -21,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
incoming_payload "code.gitea.io/gitea/services/mailer/incoming/payload"
sender_service "code.gitea.io/gitea/services/mailer/sender"
"code.gitea.io/gitea/services/mailer/token"
@@ -122,9 +123,7 @@ func composeIssueCommentMessages(ctx context.Context, comment *mailComment, lang
var mailSubject bytes.Buffer
if err := LoadedTemplates().SubjectTemplates.ExecuteTemplate(&mailSubject, tplName, mailMeta); err == nil {
subject = sanitizeSubject(mailSubject.String())
if subject == "" {
subject = fallback
}
subject = util.IfZero(subject, fallback)
} else {
log.Error("ExecuteTemplate [%s]: %v", tplName+"/subject", err)
}
@@ -183,7 +182,7 @@ func composeIssueCommentMessages(ctx context.Context, comment *mailComment, lang
if err != nil {
log.Error("CreateToken failed: %v", err)
} else {
replyAddress := strings.Replace(setting.IncomingEmail.ReplyToAddress, setting.IncomingEmail.TokenPlaceholder, token, 1)
replyAddress := strings.Replace(setting.IncomingEmail.ReplyToAddress, setting.IncomingEmailTokenPlaceholder, token, 1)
msg.ReplyTo = replyAddress
msg.SetHeader("List-Post", fmt.Sprintf("<mailto:%s>", replyAddress))
@@ -195,7 +194,7 @@ func composeIssueCommentMessages(ctx context.Context, comment *mailComment, lang
if err != nil {
log.Error("CreateToken failed: %v", err)
} else {
unsubAddress := strings.Replace(setting.IncomingEmail.ReplyToAddress, setting.IncomingEmail.TokenPlaceholder, token, 1)
unsubAddress := strings.Replace(setting.IncomingEmail.ReplyToAddress, setting.IncomingEmailTokenPlaceholder, token, 1)
listUnsubscribe = append(listUnsubscribe, "<mailto:"+unsubAddress+">")
}
}
@@ -203,7 +202,7 @@ func composeIssueCommentMessages(ctx context.Context, comment *mailComment, lang
msg.SetHeader("References", references...)
msg.SetHeader("List-Unsubscribe", listUnsubscribe...)
for key, value := range generateAdditionalHeadersForIssue(comment, actType, recipient) {
for key, value := range generateAdditionalHeadersForIssue(ctx, comment, actType, recipient) {
msg.SetHeader(key, value)
}
@@ -261,14 +260,14 @@ func actionToTemplate(issue *issues_model.Issue, actionType activities_model.Act
}
template = "repo/" + typeName + "/" + name
ok := LoadedTemplates().BodyTemplates.Lookup(template) != nil
ok := LoadedTemplates().BodyTemplates.HasTemplate(template)
if !ok && typeName != "issue" {
template = "repo/issue/" + name
ok = LoadedTemplates().BodyTemplates.Lookup(template) != nil
ok = LoadedTemplates().BodyTemplates.HasTemplate(template)
}
if !ok {
template = "repo/" + typeName + "/default"
ok = LoadedTemplates().BodyTemplates.Lookup(template) != nil
ok = LoadedTemplates().BodyTemplates.HasTemplate(template)
}
if !ok {
template = "repo/issue/default"
@@ -303,17 +302,17 @@ func generateMessageIDForIssue(issue *issues_model.Issue, comment *issues_model.
return fmt.Sprintf("<%s/%s/%d%s@%s>", issue.Repo.FullName(), path, issue.Index, extra, setting.Domain)
}
func generateAdditionalHeadersForIssue(ctx *mailComment, reason string, recipient *user_model.User) map[string]string {
repo := ctx.Issue.Repo
func generateAdditionalHeadersForIssue(ctx context.Context, comment *mailComment, reason string, recipient *user_model.User) map[string]string {
repo := comment.Issue.Repo
issueID := strconv.FormatInt(ctx.Issue.Index, 10)
issueID := strconv.FormatInt(comment.Issue.Index, 10)
headers := generateMetadataHeaders(repo)
maps.Copy(headers, generateSenderRecipientHeaders(ctx.Doer, recipient))
maps.Copy(headers, generateSenderRecipientHeaders(comment.Doer, recipient))
maps.Copy(headers, generateReasonHeaders(reason))
headers["X-Gitea-Issue-ID"] = issueID
headers["X-Gitea-Issue-Link"] = ctx.Issue.HTMLURL(context.TODO()) // FIXME: use proper context
headers["X-Gitea-Issue-Link"] = comment.Issue.HTMLURL(ctx)
headers["X-GitLab-Issue-IID"] = issueID
return headers
@@ -10,6 +10,7 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
sender_service "code.gitea.io/gitea/services/mailer/sender"
"github.com/stretchr/testify/assert"
@@ -19,18 +20,10 @@ import (
func TestMailNewReleaseFiltersUnauthorizedWatchers(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
origMailService := setting.MailService
origDomain := setting.Domain
origAppName := setting.AppName
origAppURL := setting.AppURL
origTemplates := LoadedTemplates()
defer func() {
setting.MailService = origMailService
setting.Domain = origDomain
setting.AppName = origAppName
setting.AppURL = origAppURL
loadedTemplates.Store(origTemplates)
}()
defer test.MockVariableValue(&setting.MailService)()
defer test.MockVariableValue(&setting.Domain)()
defer test.MockVariableValue(&setting.AppName)()
defer test.MockVariableValue(&setting.AppURL)()
setting.MailService = &setting.Mailer{
From: "Gitea",
@@ -39,7 +32,7 @@ func TestMailNewReleaseFiltersUnauthorizedWatchers(t *testing.T) {
setting.Domain = "example.com"
setting.AppName = "Gitea"
setting.AppURL = "https://example.com/"
prepareMailTemplates(string(tplNewReleaseMail), "{{.Subject}}", "<p>{{.Release.TagName}}</p>")
defer mockMailTemplates(string(tplNewReleaseMail), "{{.Subject}}", "<p>{{.Release.TagName}}</p>")()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
require.True(t, repo.IsPrivate)
@@ -96,11 +96,8 @@ func prepareMailerBase64Test(t *testing.T) (doer *user_model.User, repo *repo_mo
return user, repo, issue, att1, att2
}
func prepareMailTemplates(name, subjectTmpl, bodyTmpl string) {
loadedTemplates.Store(&templates.MailTemplates{
SubjectTemplates: texttmpl.Must(texttmpl.New(name).Parse(subjectTmpl)),
BodyTemplates: template.Must(template.New(name).Parse(bodyTmpl)),
})
func mockMailTemplates(name, subjectTmpl, bodyTmpl string) func() {
return templates.MailRenderer().MockTemplate(name, subjectTmpl, bodyTmpl)
}
func TestComposeIssueComment(t *testing.T) {
@@ -112,10 +109,8 @@ func TestComposeIssueComment(t *testing.T) {
},
})
setting.IncomingEmail.Enabled = true
defer func() { setting.IncomingEmail.Enabled = false }()
prepareMailTemplates("repo/issue/comment", subjectTpl, bodyTpl)
defer test.MockVariableValue(&setting.IncomingEmail.Enabled, true)()
defer mockMailTemplates("repo/issue/comment", subjectTpl, bodyTpl)()
recipients := []*user_model.User{{Name: "Test", Email: "test@gitea.com"}, {Name: "Test2", Email: "test2@gitea.com"}}
msgs, err := composeIssueCommentMessages(t.Context(), &mailComment{
@@ -160,7 +155,7 @@ func TestComposeIssueComment(t *testing.T) {
func TestMailMentionsComment(t *testing.T) {
doer, _, issue, comment := prepareMailerTest(t)
comment.Poster = doer
prepareMailTemplates("repo/issue/comment", subjectTpl, bodyTpl)
defer mockMailTemplates("repo/issue/comment", subjectTpl, bodyTpl)()
mails := 0
defer test.MockVariableValue(&SendAsync, func(msgs ...*sender_service.Message) {
@@ -175,7 +170,7 @@ func TestMailMentionsComment(t *testing.T) {
func TestComposeIssueMessage(t *testing.T) {
doer, _, issue, _ := prepareMailerTest(t)
prepareMailTemplates("repo/issue/new", subjectTpl, bodyTpl)
defer mockMailTemplates("repo/issue/new", subjectTpl, bodyTpl)()
recipients := []*user_model.User{{Name: "Test", Email: "test@gitea.com"}, {Name: "Test2", Email: "test2@gitea.com"}}
msgs, err := composeIssueCommentMessages(t.Context(), &mailComment{
Issue: issue, Doer: doer, ActionType: activities_model.ActionCreateIssue,
@@ -204,14 +199,10 @@ func TestTemplateSelection(t *testing.T) {
doer, repo, issue, comment := prepareMailerTest(t)
recipients := []*user_model.User{{Name: "Test", Email: "test@gitea.com"}}
prepareMailTemplates("repo/issue/default", "repo/issue/default/subject", "repo/issue/default/body")
texttmpl.Must(LoadedTemplates().SubjectTemplates.New("repo/issue/new").Parse("repo/issue/new/subject"))
texttmpl.Must(LoadedTemplates().SubjectTemplates.New("repo/pull/comment").Parse("repo/pull/comment/subject"))
texttmpl.Must(LoadedTemplates().SubjectTemplates.New("repo/issue/close").Parse("")) // Must default to a fallback subject
template.Must(LoadedTemplates().BodyTemplates.New("repo/issue/new").Parse("repo/issue/new/body"))
template.Must(LoadedTemplates().BodyTemplates.New("repo/pull/comment").Parse("repo/pull/comment/body"))
template.Must(LoadedTemplates().BodyTemplates.New("repo/issue/close").Parse("repo/issue/close/body"))
defer mockMailTemplates("repo/issue/default", "repo/issue/default/subject", "repo/issue/default/body")()
defer mockMailTemplates("repo/issue/new", "repo/issue/new/subject", "repo/issue/new/body")()
defer mockMailTemplates("repo/pull/comment", "repo/pull/comment/subject", "repo/pull/comment/body")()
defer mockMailTemplates("repo/issue/close", "", "repo/issue/close/body")() // Must default to a fallback subject
expect := func(t *testing.T, msg *sender_service.Message, expSubject, expBody string) {
subject := msg.ToMessage().GetGenHeader("Subject")
@@ -256,7 +247,7 @@ func TestTemplateServices(t *testing.T) {
expect := func(t *testing.T, issue *issues_model.Issue, comment *issues_model.Comment, doer *user_model.User,
actionType activities_model.ActionType, fromMention bool, tplSubject, tplBody, expSubject, expBody string,
) {
prepareMailTemplates("repo/issue/default", tplSubject, tplBody)
defer mockMailTemplates("repo/issue/default", tplSubject, tplBody)()
recipients := []*user_model.User{{Name: "Test", Email: "test@gitea.com"}}
msg := testComposeIssueCommentMessage(t, &mailComment{
Issue: issue, Doer: doer, ActionType: actionType,
@@ -304,7 +295,7 @@ func TestGenerateAdditionalHeadersForIssue(t *testing.T) {
comment := &mailComment{Issue: issue, Doer: doer}
recipient := &user_model.User{Name: "test", Email: "test@gitea.com"}
headers := generateAdditionalHeadersForIssue(comment, "dummy-reason", recipient)
headers := generateAdditionalHeadersForIssue(t.Context(), comment, "dummy-reason", recipient)
expected := map[string]string{
"List-ID": "user2/repo1 <repo1.user2.localhost>",
@@ -523,7 +514,7 @@ func TestEmbedBase64Images(t *testing.T) {
att2ImgBase64 := fmt.Sprintf(`<img src="%s"/>`, att2Base64)
t.Run("ComposeMessage", func(t *testing.T) {
prepareMailTemplates("repo/issue/new", subjectTpl, bodyTpl)
defer mockMailTemplates("repo/issue/new", subjectTpl, bodyTpl)()
issue.Content = fmt.Sprintf(`MSG-BEFORE <image src="attachments/%s"> MSG-AFTER`, att1.UUID)
require.NoError(t, issues_model.UpdateIssueCols(t.Context(), issue, "content"))
@@ -149,30 +149,31 @@ func composeAndSendActionsWorkflowRunStatusEmail(ctx context.Context, repo *repo
return nil
}
func MailActionsTrigger(ctx context.Context, sender *user_model.User, repo *repo_model.Repository, run *actions_model.ActionRun) error {
func MailActionsTrigger(ctx context.Context, recipient *user_model.User, repo *repo_model.Repository, run *actions_model.ActionRun) error {
if setting.MailService == nil {
return nil
}
if !run.Status.IsDone() || run.Status.IsSkipped() {
return nil
}
recipients := make([]*user_model.User, 0)
if !sender.IsGiteaActions() && !sender.IsGhost() && sender.IsMailable() {
notifyPref, err := user_model.GetUserSetting(ctx, sender.ID,
user_model.SettingsKeyEmailNotificationGiteaActions, user_model.SettingEmailNotificationGiteaActionsFailureOnly)
if err != nil {
return err
}
if notifyPref == user_model.SettingEmailNotificationGiteaActionsAll || !run.Status.IsSuccess() && notifyPref != user_model.SettingEmailNotificationGiteaActionsDisabled {
recipients = append(recipients, sender)
}
if !recipient.IsMailable() {
return nil
}
if len(recipients) > 0 {
log.Debug("MailActionsTrigger: Initiate email composition")
return composeAndSendActionsWorkflowRunStatusEmail(ctx, repo, run, sender, recipients)
notifyPref, err := user_model.GetUserSetting(ctx, recipient.ID,
user_model.SettingsKeyEmailNotificationGiteaActions, user_model.SettingEmailNotificationGiteaActionsFailureOnly)
if err != nil {
return err
}
return nil
// "disabled" never sends
if notifyPref == user_model.SettingEmailNotificationGiteaActionsDisabled {
return nil
}
// "failure-only" skips non-failure runs
if notifyPref != user_model.SettingEmailNotificationGiteaActionsAll && !run.Status.IsFailure() {
return nil
}
log.Debug("MailActionsTrigger: Initiate email composition")
return composeAndSendActionsWorkflowRunStatusEmail(ctx, repo, run, recipient, []*user_model.User{recipient})
}
@@ -43,7 +43,7 @@ func NewContext(ctx context.Context) {
sender = &sender_service.SMTPSender{}
}
templates.LoadMailTemplates(ctx, &loadedTemplates)
_ = templates.MailRenderer()
mailQueue = queue.CreateSimpleQueue(graceful.GetManager().ShutdownContext(), "mail", func(items ...*sender_service.Message) []*sender_service.Message {
for _, msg := range items {
@@ -41,19 +41,17 @@ func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
}
type ntlmAuth struct {
username, password, domain string
domainNeeded bool
username, password string
}
// NtlmAuth SMTP AUTH NTLM Auth Handler
func NtlmAuth(username, password string) smtp.Auth {
user, domain, domainNeeded := ntlmssp.GetDomain(username)
return &ntlmAuth{user, password, domain, domainNeeded}
return &ntlmAuth{username, password}
}
// Start starts SMTP NTLM Auth
func (a *ntlmAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
negotiateMessage, err := ntlmssp.NewNegotiateMessage(a.domain, "")
negotiateMessage, err := ntlmssp.NewNegotiateMessage("", "")
return "NTLM", negotiateMessage, err
}
@@ -63,7 +61,7 @@ func (a *ntlmAuth) Next(fromServer []byte, more bool) ([]byte, error) {
if len(fromServer) == 0 {
return nil, errors.New("ntlm ChallengeMessage is empty")
}
authenticateMessage, err := ntlmssp.ProcessChallenge(fromServer, a.username, a.password, a.domainNeeded)
authenticateMessage, err := ntlmssp.NewAuthenticateMessage(fromServer, a.username, a.password, nil)
return authenticateMessage, err
}
return nil, nil
@@ -9,6 +9,7 @@ import (
"crypto/sha256"
"encoding/base32"
"fmt"
"strings"
"time"
user_model "code.gitea.io/gitea/models/user"
@@ -73,9 +74,11 @@ func CreateToken(ht HandlerType, user *user_model.User, data []byte) (string, er
return encodingWithoutPadding.EncodeToString(append([]byte{tokenVersion1}, packagedData...)), nil
}
// ExtractToken extracts the action/user tuple from the token and verifies the content
func ExtractToken(ctx context.Context, token string) (HandlerType, *user_model.User, []byte, error) {
data, err := encodingWithoutPadding.DecodeString(token)
// DecodeToken decodes the handler, user and payload from the token and verifies the content
func DecodeToken(ctx context.Context, token string) (HandlerType, *user_model.User, []byte, error) {
// MTAs are permitted to alter the case of the local-part (RFC 5321 §2.4), so normalize
// to the base32 alphabet before decoding to survive a lowercased reply-to address.
data, err := encodingWithoutPadding.DecodeString(strings.ToUpper(token))
if err != nil {
return UnknownHandlerType, nil, nil, err
}
@@ -118,11 +121,11 @@ func ExtractToken(ctx context.Context, token string) (HandlerType, *user_model.U
return handlerType, user, innerPayload, nil
}
// generateHmac creates a trunkated HMAC for the given payload
// generateHmac creates a truncated HMAC for the given payload
func generateHmac(secret, payload []byte) []byte {
mac := crypto_hmac.New(sha256.New, secret)
mac.Write(payload)
hmac := mac.Sum(nil)
return hmac[:10] // RFC2104 recommends not using less then 80 bits
return hmac[:10] // RFC2104 recommends not using less than 80 bits
}