diff --git a/contrib/backends/srndv2/src/srnd/config.go b/contrib/backends/srndv2/src/srnd/config.go index 0a7dc46..21357fe 100644 --- a/contrib/backends/srndv2/src/srnd/config.go +++ b/contrib/backends/srndv2/src/srnd/config.go @@ -8,6 +8,7 @@ import ( "bufio" "bytes" "encoding/base32" + "encoding/hex" "fmt" "github.com/majestrate/configparser" "io/ioutil" @@ -187,6 +188,7 @@ func GenSRNdConfig() *configparser.Configuration { sect.Add("archive", "0") sect.Add("article_lifetime", "0") sect.Add("filters_file", "filters.txt") + sect.Add("secretkey", hex.EncodeToString(randbytes(32))) // spamd settings sect = conf.NewSection("spamd") diff --git a/contrib/backends/srndv2/src/srnd/database.go b/contrib/backends/srndv2/src/srnd/database.go index dca83ca..0cfb6de 100644 --- a/contrib/backends/srndv2/src/srnd/database.go +++ b/contrib/backends/srndv2/src/srnd/database.go @@ -305,10 +305,12 @@ type Database interface { GetMessageIDByEncryptedIP(encaddr string) ([]string, error) // check if this public key is banned from posting - PubkeyIsBanned(pubkey string) (bool, error) + PubkeyRejected(pubkey string) (bool, error) // ban a public key from posting - BanPubkey(pubkey string) error + BlacklistPubkey(pubkey string) error + WhitelistPubkey(pubkey string) error + DeletePubkey(pubkey string) error // get all message-id posted before a time GetPostsBefore(t time.Time) ([]string, error) diff --git a/contrib/backends/srndv2/src/srnd/message.go b/contrib/backends/srndv2/src/srnd/message.go index 944e8fb..68445b2 100644 --- a/contrib/backends/srndv2/src/srnd/message.go +++ b/contrib/backends/srndv2/src/srnd/message.go @@ -89,6 +89,7 @@ type NNTPMessage interface { OP() bool // all attachments Attachments() []NNTPAttachment + FrontendPubkey() string // all headers Headers() ArticleHeaders MIMEHeader() textproto.MIMEHeader @@ -112,6 +113,10 @@ type NNTPMessage interface { BodyReader() io.Reader } +func (self *nntpArticle) FrontendPubkey() string { + return self.headers.Get("X-Frontend-Pubkey", "") +} + type nntpArticle struct { // mime header headers ArticleHeaders diff --git a/contrib/backends/srndv2/src/srnd/model.go b/contrib/backends/srndv2/src/srnd/model.go index 04350c1..d6dcaf8 100644 --- a/contrib/backends/srndv2/src/srnd/model.go +++ b/contrib/backends/srndv2/src/srnd/model.go @@ -45,7 +45,7 @@ type PostModel interface { BaseModel CSSClass() string - + FrontendPubkey() string MessageID() string PostHash() string ShortHash() string diff --git a/contrib/backends/srndv2/src/srnd/model_mem.go b/contrib/backends/srndv2/src/srnd/model_mem.go index 96e17cd..3159302 100644 --- a/contrib/backends/srndv2/src/srnd/model_mem.go +++ b/contrib/backends/srndv2/src/srnd/model_mem.go @@ -238,34 +238,35 @@ func (self *boardModel) Update(db Database) { } type post struct { - _i18n *I18N - truncated bool - prefix string - board string - PostName string - PostSubject string - PostMessage string - message_rendered string - Message_id string - MessagePath string - addr string - Newsgroup string - op bool - Posted int64 - Parent string - sage bool - Key string - Files []AttachmentModel - HashLong string - HashShort string - URL string - Tripcode string - BodyMarkup string - PostMarkup string - PostPrefix string - index int - Type string - nntp_id int + _i18n *I18N + truncated bool + prefix string + board string + PostName string + PostSubject string + PostMessage string + message_rendered string + Message_id string + MessagePath string + addr string + Newsgroup string + op bool + Posted int64 + Parent string + sage bool + Key string + Files []AttachmentModel + HashLong string + HashShort string + URL string + Tripcode string + BodyMarkup string + PostMarkup string + PostPrefix string + index int + Type string + nntp_id int + FrontendPublicKey string } func (self *post) NNTPID() int { @@ -378,6 +379,7 @@ func PostModelFromMessage(parent, prefix string, nntp NNTPMessage) PostModel { p.addr = nntp.Addr() p.sage = nntp.Sage() p.Key = nntp.Pubkey() + p.FrontendPublicKey = nntp.FrontendPubkey() for _, att := range nntp.Attachments() { p.Files = append(p.Files, att.ToModel(prefix)) } @@ -411,6 +413,10 @@ func (self *post) PubkeyHex() string { return self.Key } +func (self *post) FrontendPubkey() string { + return self.FrontendPublicKey +} + func (self *post) Pubkey() string { if len(self.Key) > 0 { return fmt.Sprintf("", self.Key, makeTripcode(self.Key)) @@ -559,7 +565,8 @@ func (self *post) Truncate() PostModel { sage: self.sage, Key: self.Key, // TODO: copy? - Files: self.Files, + Files: self.Files, + FrontendPublicKey: self.FrontendPublicKey, } } diff --git a/contrib/backends/srndv2/src/srnd/nntp.go b/contrib/backends/srndv2/src/srnd/nntp.go index 2eb2512..e8466aa 100644 --- a/contrib/backends/srndv2/src/srnd/nntp.go +++ b/contrib/backends/srndv2/src/srnd/nntp.go @@ -422,7 +422,7 @@ func (self *nntpConnection) checkMIMEHeaderNoAuth(daemon *NNTPDaemon, hdr textpr } if serverPubkeyIsValid(server_pubkey) { - b, _ := daemon.database.PubkeyIsBanned(server_pubkey) + b, _ := daemon.database.PubkeyRejected(server_pubkey) if b { reason = "server's pubkey is banned" ban = true @@ -448,7 +448,7 @@ func (self *nntpConnection) checkMIMEHeaderNoAuth(daemon *NNTPDaemon, hdr textpr reason = "newsgroup banned" ban = true return - } else if banned, _ = daemon.database.PubkeyIsBanned(pubkey); banned { + } else if banned, _ = daemon.database.PubkeyRejected(pubkey); banned { // check for banned pubkey reason = "poster's pubkey is banned" ban = true diff --git a/contrib/backends/srndv2/src/srnd/postgres.go b/contrib/backends/srndv2/src/srnd/postgres.go index 3bdf825..041ba9a 100644 --- a/contrib/backends/srndv2/src/srnd/postgres.go +++ b/contrib/backends/srndv2/src/srnd/postgres.go @@ -186,7 +186,7 @@ func (self *PostgresDatabase) prepareStatements() { GetPostAttachmentModels: "SELECT filepath, filename FROM ArticleAttachments WHERE message_id = $1", RegisterArticle_1: "INSERT INTO Articles (message_id, message_id_hash, message_newsgroup, time_obtained, message_ref_id) VALUES($1, $2, $3, $4, $5)", RegisterArticle_2: "UPDATE Newsgroups SET last_post = $1 WHERE name = $2", - RegisterArticle_3: "INSERT INTO ArticlePosts(newsgroup, message_id, ref_id, name, subject, path, time_posted, message, addr) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9)", + RegisterArticle_3: "INSERT INTO ArticlePosts(newsgroup, message_id, ref_id, name, subject, path, time_posted, message, addr, frontendpubkey) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", RegisterArticle_4: "INSERT INTO ArticleThreads(root_message_id, last_bump, last_post, newsgroup) VALUES($1, $2, $2, $3)", RegisterArticle_5: "SELECT COUNT(*) FROM ArticlePosts WHERE ref_id = $1", RegisterArticle_6: "UPDATE ArticleThreads SET last_bump = $2 WHERE root_message_id = $1", @@ -257,6 +257,8 @@ func (self *PostgresDatabase) CreateTables() { } else if version == 7 { self.upgrade7to8() } else if version == 8 { + self.upgrade8to9() + } else if version == 9 { // we are up to date log.Println("we are up to date at version", version) break @@ -617,6 +619,18 @@ func (self *PostgresDatabase) upgrade7to8() { self.setDBVersion(8) } +func (self *PostgresDatabase) upgrade8to9() { + _, err := self.conn.Exec("ALTER TABLE ArticlePosts ADD COLUMN IF NOT EXISTS frontendpubkey TEXT NOT NULL DEFAULT ''") + if err != nil { + log.Fatalf(err.Error()) + } + _, err = self.conn.Exec("CREATE TABLE IF NOT EXISTS nntpchan_pubkeys(status VARCHAR(16) NOT NULL, pubkey VARCHAR(64) PRIMARY KEY)") + if err != nil { + log.Fatalf(err.Error()) + } + self.setDBVersion(9) +} + // create all tables for database version 0 func (self *PostgresDatabase) createTablesV0() { tables := make(map[string]string) @@ -1474,7 +1488,7 @@ func (self *PostgresDatabase) RegisterArticle(message NNTPMessage) (err error) { return } // insert article post - _, err = self.conn.Exec(self.stmt[RegisterArticle_3], group, msgid, message.Reference(), message.Name(), message.Subject(), message.Path(), message.Posted(), message.Message(), message.Addr()) + _, err = self.conn.Exec(self.stmt[RegisterArticle_3], group, msgid, message.Reference(), message.Name(), message.Subject(), message.Path(), message.Posted(), message.Message(), message.Addr(), message.FrontendPubkey()) if err != nil { log.Println("cannot insert article post", err) return @@ -1877,7 +1891,6 @@ func (self *PostgresDatabase) GetMessageIDByEncryptedIP(encaddr string) (msgids if err == nil { msgids = append(msgids, msgid) } - } if rows != nil { rows.Close() @@ -1885,15 +1898,32 @@ func (self *PostgresDatabase) GetMessageIDByEncryptedIP(encaddr string) (msgids return } -func (self *PostgresDatabase) BanPubkey(pubkey string) (err error) { - // TODO: implement - err = errors.New("ban pubkey not implemented") +func (self *PostgresDatabase) WhitelistPubkey(pubkey string) (err error) { + _, err = self.conn.Exec("INSERT INTO nntpchan_pubkeys VALUES ('whitelist', $1)", pubkey) return } -func (self *PostgresDatabase) PubkeyIsBanned(pubkey string) (bool, error) { - // TODO: implement - return false, nil +func (self *PostgresDatabase) DeletePubkey(pubkey string) (err error) { + _, err = self.conn.Exec("DELETE FROM nntpchan_pubkeys WHERE pubkey = $1", pubkey) + return +} + +func (self *PostgresDatabase) BlacklistPubkey(pubkey string) (err error) { + _, err = self.conn.Exec("INSERT INTO nntpchan_pubkeys VALUES ('blacklist', $1)", pubkey) + return +} + +// return true if we should drop this message with this frontend pubkey +func (self *PostgresDatabase) PubkeyRejected(pubkey string) (bool, error) { + var num int64 + var drop bool + var err error + err = self.conn.QueryRow("SELECT COUNT(pubkey) FROM nntpchan_pubkeys WHERE pubkey = $1 AND status = 'whitelist'", pubkey).Scan(&num) + if err == nil && num == 0 { + err = self.conn.QueryRow("SELECT COUNT(pubkey) FROM nntpchan_pubkeys WHERE pubkey = $1 and status = 'blacklist'", pubkey).Scan(&num) + drop = num > 0 + } + return drop, err } func (self *PostgresDatabase) GetPostsBefore(t time.Time) (msgids []string, err error) { diff --git a/contrib/backends/srndv2/srnd.go b/contrib/backends/srndv2/srnd.go index 6988ee1..85b6a27 100644 --- a/contrib/backends/srndv2/srnd.go +++ b/contrib/backends/srndv2/srnd.go @@ -128,11 +128,27 @@ func main() { } else { fmt.Fprintf(os.Stdout, "Usage: %s tool nntp add-login username password\n", os.Args[0]) } + } else if action == "whitelist" { + daemon.Setup() + err := daemon.GetDatabase().WhitelistPubkey(os.Args[4]) + if err == nil { + fmt.Println("OK") + } else { + fmt.Println(err) + } + } else if action == "blacklist" { + daemon.Setup() + err := daemon.GetDatabase().BlacklistPubkey(os.Args[4]) + if err == nil { + fmt.Println("OK") + } else { + fmt.Println(err) + } } else { - fmt.Fprintf(os.Stdout, "Usage: %s tool nntp [add-login|del-login]\n", os.Args[0]) + fmt.Fprintf(os.Stdout, "Usage: %s tool nntp [add-login|del-login|whitelist|blacklist]\n", os.Args[0]) } } else { - fmt.Fprintf(os.Stdout, "Usage: %s tool nntp [add-login|del-login]\n", os.Args[0]) + fmt.Fprintf(os.Stdout, "Usage: %s tool nntp [add-login|del-login|whitelist|blacklist]\n", os.Args[0]) } } else { fmt.Fprintf(os.Stdout, "Usage: %s tool [rethumb|keygen|nntp|mod|expire]\n", os.Args[0])