diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index e53671d9..00000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -vendor/* linguist-vendored -languages/* linguist-vendored diff --git a/.goreleaser.yml b/.goreleaser.yml deleted file mode 100644 index 8412eb12..00000000 --- a/.goreleaser.yml +++ /dev/null @@ -1,56 +0,0 @@ -# .goreleaser.yml -# Build customization -project_name: ergo -builds: - - main: ergo.go - binary: ergo - goos: - - freebsd - - windows - - darwin - - linux - goarch: - - "386" - - amd64 - - arm - - arm64 - goarm: - - 6 - - 7 - ignore: - - goos: windows - goarch: arm - - goos: darwin - goarch: arm - - goos: darwin - goarch: 386 - - goos: freebsd - goarch: arm - - goos: freebsd - goarch: arm64 - flags: - - -trimpath - -archives: - - name_template: "{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - format: tar.gz - replacements: - amd64: x86_64 - darwin: macos - format_overrides: - - goos: windows - format: zip - files: - - README - - CHANGELOG.md - - ergo.motd - - default.yaml - - traditional.yaml - - docs/MANUAL.md - - docs/USERGUIDE.md - - languages/*.yaml - - languages/*.json - - languages/*.md - wrap_in_directory: true -checksum: - name_template: "{{ .ProjectName }}-{{ .Version }}-checksums.txt" diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index ab45eb3c..00000000 --- a/Dockerfile +++ /dev/null @@ -1,48 +0,0 @@ -## build ergo binary -FROM golang:1.17-alpine AS build-env - -RUN apk add -U --force-refresh --no-cache --purge --clean-protected -l -u make - -# copy ergo source -WORKDIR /go/src/github.com/ergochat/ergo -COPY . . - -# modify default config file so that it doesn't die on IPv6 -# and so it can be exposed via 6667 by default -RUN sed -i 's/^\(\s*\)\"127.0.0.1:6667\":.*$/\1":6667":/' /go/src/github.com/ergochat/ergo/default.yaml && \ - sed -i 's/^\s*\"\[::1\]:6667\":.*$//' /go/src/github.com/ergochat/ergo/default.yaml - -# compile -RUN make - -## build ergo container -FROM alpine:3.13 - -# metadata -LABEL maintainer="Daniel Oaks ,Daniel Thamdrup " \ - description="Ergo is a modern, experimental IRC server written in Go" - -# standard ports listened on -EXPOSE 6667/tcp 6697/tcp - -# ergo itself -COPY --from=build-env /go/bin/ergo \ - /go/src/github.com/ergochat/ergo/default.yaml \ - /go/src/github.com/ergochat/ergo/distrib/docker/run.sh \ - /ircd-bin/ -COPY --from=build-env /go/src/github.com/ergochat/ergo/languages /ircd-bin/languages/ - -# running volume holding config file, db, certs -VOLUME /ircd -WORKDIR /ircd - -# default motd -COPY --from=build-env /go/src/github.com/ergochat/ergo/ergo.motd /ircd/ergo.motd - -# launch -ENTRYPOINT ["/ircd-bin/run.sh"] - -# # uncomment to debug -# RUN apk add --no-cache bash -# RUN apk add --no-cache vim -# CMD /bin/bash diff --git a/LICENSE b/LICENSE index acbac131..779814db 100644 --- a/LICENSE +++ b/LICENSE @@ -4,6 +4,7 @@ Copyright (c) 2012-2014 Jeremy Latt Copyright (c) 2014-2015 Edmund Huber Copyright (c) 2016-2020 Daniel Oaks Copyright (c) 2017-2020 Shivaram Lingamneni +Copyright (c) 2020-2022 kayos@tcp.direct Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/irc/accounts.go b/irc/accounts.go index 399d424b..808ab0b0 100644 --- a/irc/accounts.go +++ b/irc/accounts.go @@ -194,8 +194,8 @@ func (am *AccountManager) buildNickToAccountIndex(config *Config) { if config.Accounts.NickReservation.Method == NickEnforcementStrict { unregisteredPrefix := fmt.Sprintf(keyAccountUnregistered, "") - am.server.store.View(func(tx *buntdb.Tx) error { - tx.AscendGreaterOrEqual("", unregisteredPrefix, func(key, value string) bool { + err := am.server.store.View(func(tx *buntdb.Tx) error { + err = tx.AscendGreaterOrEqual("", unregisteredPrefix, func(key, value string) bool { if !strings.HasPrefix(key, unregisteredPrefix) { return false } @@ -206,8 +206,11 @@ func (am *AccountManager) buildNickToAccountIndex(config *Config) { skeletonToAccount[skeleton] = account return true }) - return nil + return err }) + if err != nil { + am.server.logger.Error("internal", "buildNickToAccountIndex buntdb transaction error during AscendGreaterOrEqual", err.Error()) + } } if err != nil { @@ -403,7 +406,10 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames if err != nil { return err } - creds.AddCertfp(certfp) + err = creds.AddCertfp(certfp) + if err != nil { + return err + } credStr, err := creds.Serialize() if err != nil { return err @@ -471,7 +477,7 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames code, err := am.dispatchCallback(client, account, callbackNamespace, callbackValue) if err != nil { - am.Unregister(casefoldedAccount, true) + _ = am.Unregister(casefoldedAccount, true) return ®istrationCallbackError{underlying: err} } else { am.server.logger.Info("accounts", @@ -537,11 +543,11 @@ func (am *AccountManager) setPassword(accountName string, password string, hasPr credKey := fmt.Sprintf(keyAccountCredentials, cfAccount) var credStr string - am.server.store.View(func(tx *buntdb.Tx) error { + err = am.server.store.View(func(tx *buntdb.Tx) error { // no need to check verification status here or below; // you either need to be auth'ed to the account or be an oper to do this credStr, err = tx.Get(credKey) - return nil + return err }) if err != nil { @@ -651,12 +657,14 @@ func (am *AccountManager) saveLastSeen(account string, lastSeen map[string]time. val = string(text) } err := am.server.store.Update(func(tx *buntdb.Tx) error { - if val != "" { - tx.Set(key, val, nil) - } else { - tx.Delete(key) + var err error + switch val { + case "": + _, err = tx.Delete(key) + default: + _, _, err = tx.Set(key, val, nil) } - return nil + return err }) if err != nil { am.server.logger.Error("internal", "error persisting lastSeen", account, err.Error()) @@ -714,9 +722,9 @@ func (am *AccountManager) addRemoveCertfp(account, certfp string, add bool, hasP credKey := fmt.Sprintf(keyAccountCredentials, cfAccount) var credStr string - am.server.store.View(func(tx *buntdb.Tx) error { + err = am.server.store.View(func(tx *buntdb.Tx) error { credStr, err = tx.Get(credKey) - return nil + return err }) if err != nil { @@ -733,16 +741,18 @@ func (am *AccountManager) addRemoveCertfp(account, certfp string, add bool, hasP return errCredsExternallyManaged } - if add { + switch add { + case true: err = creds.AddCertfp(certfp) - } else { + default: err = creds.RemoveCertfp(certfp) } + if err != nil { return err } - if creds.Empty() && !hasPrivs { + if creds.Empty() { return errEmptyCredentials } diff --git a/irc/database.go b/irc/database.go index dc5a69fa..92e4ba1e 100644 --- a/irc/database.go +++ b/irc/database.go @@ -24,8 +24,7 @@ const ( // 'version' of the database schema keySchemaVersion = "db.version" // latest schema of the db - latestDbSchema = 22 - + latestDbSchema = 23 keyCloakSecret = "crypto.cloak_secret" ) @@ -1113,6 +1112,56 @@ func schemaChangeV21To22(config *Config, tx *buntdb.Tx) error { return nil } +func schemaChangeV22To23(config *Config, tx *buntdb.Tx) error { + type accountSettingsv23 struct { + NickEnforcement NickEnforcementMethod + AllowBouncer MulticlientAllowedSetting + AutoreplayMissed bool + AutoAway PersistentStatus + GitAuth bool + Email string + } + + var accounts []string + var serializedSettings []string + settingsPrefix := "account.settings " + err := tx.AscendGreaterOrEqual("", settingsPrefix, func(key, value string) bool { + if !strings.HasPrefix(key, settingsPrefix) { + return false + } + if value == "" { + return true + } + account := strings.TrimPrefix(key, settingsPrefix) + var settings accountSettingsv23 + err := json.Unmarshal([]byte(value), &settings) + if err != nil { + log.Printf("error (v22-23) processing settings for %s: %v\n", account, err) + return true + } + + b, err := json.Marshal(settings) + + if err != nil { + log.Printf("error (v22-23) processing settings for %s: %v\n", account, err) + return true + } + + accounts = append(accounts, account) + serializedSettings = append(serializedSettings, string(b)) + return true + }) + + if err != nil { + log.Printf("error (v22-23) processing db transaction (invalid index): %v\n", err) + } + + for i, account := range accounts { + tx.Set(settingsPrefix+account, serializedSettings[i], nil) + } + return nil +} + func getSchemaChange(initialVersion int) (result SchemaChange, ok bool) { for _, change := range allChanges { if initialVersion == change.InitialVersion { @@ -1228,4 +1277,9 @@ var allChanges = []SchemaChange{ TargetVersion: 22, Changer: schemaChangeV21To22, }, + { + InitialVersion: 22, + TargetVersion: 23, + Changer: schemaChangeV22To23, + }, } diff --git a/irc/nickserv.go b/irc/nickserv.go index 548a5f77..b80bb8fc 100644 --- a/irc/nickserv.go +++ b/irc/nickserv.go @@ -421,15 +421,6 @@ func displaySetting(service *ircService, settingName string, settings AccountSet service.Notice(rb, client.t("Multiclient functionality is currently enabled for your account")) } } - case "always-on": - stored := settings.AlwaysOn - actual := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, stored) - service.Notice(rb, fmt.Sprintf(client.t("Your stored always-on setting is: %s"), userPersistentStatusToString(stored))) - if actual { - service.Notice(rb, client.t("Given current server settings, your client is always-on")) - } else { - service.Notice(rb, client.t("Given current server settings, your client is not always-on")) - } case "auto-away": stored := settings.AutoAway alwaysOn := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, settings.AlwaysOn) @@ -500,22 +491,6 @@ func nsSetHandler(service *ircService, server *Server, client *Client, command s if err == nil { finalSettings.NickEnforcement = method // success } - case "autoreplay-lines": - var newValue *int - if strings.ToLower(params[1]) != "default" { - val, err_ := strconv.Atoi(params[1]) - if err_ != nil || val < 0 { - err = errInvalidParams - break - } - newValue = new(int) - *newValue = val - } - munger = func(in AccountSettings) (out AccountSettings, err error) { - out = in - out.AutoreplayLines = newValue - return - } case "multiclient": var newValue MulticlientAllowedSetting if strings.ToLower(params[1]) == "default" { @@ -546,39 +521,6 @@ func nsSetHandler(service *ircService, server *Server, client *Client, command s return } } - case "always-on": - // #821: it's problematic to alter the value of always-on if you're not - // the (actual or potential) always-on client yourself. make an exception - // for `saset` to give operators an escape hatch (any consistency problems - // can probably be fixed by restarting the server): - if command != "saset" { - details := client.Details() - if details.nick != details.accountName { - err = errNickAccountMismatch - } - } - if err == nil { - var newValue PersistentStatus - newValue, err = persistentStatusFromString(params[1]) - // "opt-in" and "opt-out" don't make sense as user preferences - if err == nil && newValue != PersistentOptIn && newValue != PersistentOptOut { - munger = func(in AccountSettings) (out AccountSettings, err error) { - out = in - out.AlwaysOn = newValue - return - } - } - } - case "autoreplay-missed": - var newValue bool - newValue, err = utils.StringToBool(params[1]) - if err == nil { - munger = func(in AccountSettings) (out AccountSettings, err error) { - out = in - out.AutoreplayMissed = newValue - return - } - } case "auto-away": var newValue PersistentStatus newValue, err = persistentStatusFromString(params[1])