more
This commit is contained in:
parent
e02f0fc3fd
commit
c965f0f7af
@ -3,9 +3,9 @@ EXE = nntpd
|
|||||||
|
|
||||||
TOOL = nntpchan-tool
|
TOOL = nntpchan-tool
|
||||||
|
|
||||||
CXX = clang++
|
CXX = g++
|
||||||
|
REPO=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||||
SRC_PATH = ./src
|
SRC_PATH = $(REPO)/src
|
||||||
|
|
||||||
SOURCES := $(wildcard $(SRC_PATH)/*.cpp)
|
SOURCES := $(wildcard $(SRC_PATH)/*.cpp)
|
||||||
HEADERS := $(wildcard $(SRC_PATH)/*.hpp)
|
HEADERS := $(wildcard $(SRC_PATH)/*.hpp)
|
||||||
@ -14,21 +14,21 @@ OBJECTS := $(SOURCES:.cpp=.o)
|
|||||||
PKGS := libuv libsodium
|
PKGS := libuv libsodium
|
||||||
|
|
||||||
LD_FLAGS := $(shell pkg-config --libs $(PKGS))
|
LD_FLAGS := $(shell pkg-config --libs $(PKGS))
|
||||||
INC_FLAGS := -I $(SRC_PATH) $(shell pkg-config --cflags $(PKGS))
|
INC_FLAGS := $(shell pkg-config --cflags $(PKGS)) -I $(REPO)/src
|
||||||
CXXFLAGS := -std=c++14 -Wall -Wextra $(INC_FLAGS) -g
|
CXXFLAGS := -std=c++11 -Wall -Wextra $(INC_FLAGS) -g
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
all: $(EXE) $(TOOL)
|
all: $(EXE) $(TOOL)
|
||||||
|
|
||||||
$(EXE): $(OBJECTS)
|
$(EXE): $(OBJECTS)
|
||||||
$(CXX) -o $(EXE) $(LD_FLAGS) $(OBJECTS) $(CXXFLAGS) nntpd.cpp
|
$(CXX) -o $(EXE) $(OBJECTS) $(CXXFLAGS) nntpd.cpp $(LD_FLAGS)
|
||||||
|
|
||||||
$(TOOL): $(OBJECTS)
|
$(TOOL): $(OBJECTS)
|
||||||
$(CXX) -o $(TOOL) $(LD_FLAGS) $(OBJECTS) $(CXXFLAGS) tool.cpp
|
$(CXX) -o $(TOOL) $(OBJECTS) $(CXXFLAGS) tool.cpp $(LD_FLAGS)
|
||||||
|
|
||||||
build-test: $(OBJECTS)
|
build-test: $(OBJECTS)
|
||||||
$(CXX) -o test $(LD_FLAGS) $(OBJECTS) $(CXXFLAGS) test.cpp
|
$(CXX) -o test $(OBJECTS) $(CXXFLAGS) test.cpp $(LD_FLAGS)
|
||||||
|
|
||||||
test: build-test
|
test: build-test
|
||||||
./test
|
./test
|
||||||
|
@ -64,7 +64,24 @@ namespace nntpchan
|
|||||||
|
|
||||||
void NNTPServerHandler::SwitchMode(const std::string & mode)
|
void NNTPServerHandler::SwitchMode(const std::string & mode)
|
||||||
{
|
{
|
||||||
|
if (mode == "READER") {
|
||||||
|
m_mode = mode;
|
||||||
|
if(PostingAllowed()) {
|
||||||
|
QueueLine("200 Posting is permitted yo");
|
||||||
|
} else {
|
||||||
|
QueueLine("201 Posting is not permitted yo");
|
||||||
|
}
|
||||||
|
} else if (mode == "STREAM") {
|
||||||
|
m_mode = mode;
|
||||||
|
if (PostingAllowed()) {
|
||||||
|
QueueLine("203 Streaming enabled");
|
||||||
|
} else {
|
||||||
|
QueueLine("483 Streaming Denied");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// unknown mode
|
||||||
|
QueueLine("500 Unknown mode");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NNTPServerHandler::Quit()
|
void NNTPServerHandler::Quit()
|
||||||
|
@ -877,7 +877,7 @@ func (self *NNTPDaemon) poll(worker int) {
|
|||||||
}
|
}
|
||||||
minconn := lowestBacklogConnection(send)
|
minconn := lowestBacklogConnection(send)
|
||||||
if minconn != nil {
|
if minconn != nil {
|
||||||
minconn.offerStream(nntp.MessageID(), sz)
|
go minconn.offerStream(nntp.MessageID(), sz)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,11 +48,22 @@ type ModUI interface {
|
|||||||
MessageChan() chan NNTPMessage
|
MessageChan() chan NNTPMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ModAction string
|
||||||
|
|
||||||
|
const ModInetBan = ModAction("overchan-inet-ban")
|
||||||
|
const ModDelete = ModAction("overchan-delete")
|
||||||
|
const ModRemoveAttachment = ModAction("overchan-del-attachment")
|
||||||
|
const ModStick = ModAction("overchan-stick")
|
||||||
|
const ModLock = ModAction("overchan-lock")
|
||||||
|
const ModHide = ModAction("overchan-hide")
|
||||||
|
const ModSage = ModAction("overchan-sage")
|
||||||
|
const ModDeleteAlt = ModAction("delete")
|
||||||
|
|
||||||
type ModEvent interface {
|
type ModEvent interface {
|
||||||
// turn it into a string for putting into an article
|
// turn it into a string for putting into an article
|
||||||
String() string
|
String() string
|
||||||
// what type of mod event
|
// what type of mod event
|
||||||
Action() string
|
Action() ModAction
|
||||||
// what reason for the event
|
// what reason for the event
|
||||||
Reason() string
|
Reason() string
|
||||||
// what is the event acting on
|
// what is the event acting on
|
||||||
@ -69,8 +80,8 @@ func (self simpleModEvent) String() string {
|
|||||||
return string(self)
|
return string(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self simpleModEvent) Action() string {
|
func (self simpleModEvent) Action() ModAction {
|
||||||
return strings.Split(string(self), " ")[0]
|
return ModAction(strings.Split(string(self), " ")[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self simpleModEvent) Reason() string {
|
func (self simpleModEvent) Reason() string {
|
||||||
@ -156,6 +167,8 @@ type ModEngine interface {
|
|||||||
AllowDelete(pubkey, msgid string) bool
|
AllowDelete(pubkey, msgid string) bool
|
||||||
// do we allow this public key to do inet-ban?
|
// do we allow this public key to do inet-ban?
|
||||||
AllowBan(pubkey string) bool
|
AllowBan(pubkey string) bool
|
||||||
|
// allow janitor
|
||||||
|
AllowJanitor(pubkey string) bool
|
||||||
// load a mod message
|
// load a mod message
|
||||||
LoadMessage(msgid string) NNTPMessage
|
LoadMessage(msgid string) NNTPMessage
|
||||||
// execute 1 mod action line by a mod with pubkey
|
// execute 1 mod action line by a mod with pubkey
|
||||||
@ -255,6 +268,18 @@ func (self *modEngine) AllowBan(pubkey string) bool {
|
|||||||
return self.database.CheckModPubkeyGlobal(pubkey)
|
return self.database.CheckModPubkeyGlobal(pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *modEngine) AllowJanitor(pubkey string) bool {
|
||||||
|
is_admin, _ := self.database.CheckAdminPubkey(pubkey)
|
||||||
|
if is_admin {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if self.database.CheckModPubkeyGlobal(pubkey) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// TODO: more checks
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (self *modEngine) AllowDelete(pubkey, msgid string) (allow bool) {
|
func (self *modEngine) AllowDelete(pubkey, msgid string) (allow bool) {
|
||||||
is_admin, _ := self.database.CheckAdminPubkey(pubkey)
|
is_admin, _ := self.database.CheckAdminPubkey(pubkey)
|
||||||
if is_admin {
|
if is_admin {
|
||||||
@ -294,7 +319,8 @@ func (mod *modEngine) HandleMessage(msgid string) {
|
|||||||
|
|
||||||
func (mod *modEngine) Do(ev ModEvent) {
|
func (mod *modEngine) Do(ev ModEvent) {
|
||||||
action := ev.Action()
|
action := ev.Action()
|
||||||
if action == "delete" {
|
target := ev.Target()
|
||||||
|
if action == ModDelete || action == ModDeleteAlt {
|
||||||
msgid := ev.Target()
|
msgid := ev.Target()
|
||||||
if !ValidMessageID(msgid) {
|
if !ValidMessageID(msgid) {
|
||||||
// invalid message-id
|
// invalid message-id
|
||||||
@ -308,9 +334,8 @@ func (mod *modEngine) Do(ev ModEvent) {
|
|||||||
log.Println("deleted", msgid)
|
log.Println("deleted", msgid)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if action == "overchan-inet-ban" {
|
} else if action == ModInetBan {
|
||||||
// ban action
|
// ban action
|
||||||
target := ev.Target()
|
|
||||||
if target[0] == '[' {
|
if target[0] == '[' {
|
||||||
err := mod.BanAddress(target)
|
err := mod.BanAddress(target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -357,6 +382,27 @@ func (mod *modEngine) Do(ev ModEvent) {
|
|||||||
} else {
|
} else {
|
||||||
log.Printf("invalid overchan-inet-ban: target=%s", target)
|
log.Printf("invalid overchan-inet-ban: target=%s", target)
|
||||||
}
|
}
|
||||||
|
} else if action == ModHide {
|
||||||
|
// TODO: implement
|
||||||
|
} else if action == ModLock {
|
||||||
|
// TODO: implement
|
||||||
|
} else if action == ModSage {
|
||||||
|
// TODO: implement
|
||||||
|
} else if action == ModStick {
|
||||||
|
// TODO: implement
|
||||||
|
} else if action == ModRemoveAttachment {
|
||||||
|
var delfiles []string
|
||||||
|
atts := mod.database.GetPostAttachments(target)
|
||||||
|
if atts != nil {
|
||||||
|
for _, att := range atts {
|
||||||
|
delfiles = append(delfiles, mod.store.AttachmentFilepath(att))
|
||||||
|
delfiles = append(delfiles, mod.store.ThumbnailFilepath(att))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, f := range delfiles {
|
||||||
|
log.Println("remove file", f)
|
||||||
|
os.Remove(f)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Println("invalid mod action", action)
|
log.Println("invalid mod action", action)
|
||||||
}
|
}
|
||||||
@ -364,77 +410,28 @@ func (mod *modEngine) Do(ev ModEvent) {
|
|||||||
|
|
||||||
func (mod *modEngine) Execute(ev ModEvent, pubkey string) {
|
func (mod *modEngine) Execute(ev ModEvent, pubkey string) {
|
||||||
action := ev.Action()
|
action := ev.Action()
|
||||||
if action == "delete" {
|
|
||||||
msgid := ev.Target()
|
|
||||||
if !ValidMessageID(msgid) {
|
|
||||||
// invalid message-id
|
|
||||||
log.Println("invalid message-id for mod delete from", pubkey)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// this is a delete action
|
|
||||||
if mod.AllowDelete(pubkey, msgid) {
|
|
||||||
err := mod.DeletePost(msgid)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(msgid, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("pubkey=%s will not delete %s not trusted", pubkey, msgid)
|
|
||||||
}
|
|
||||||
} else if action == "overchan-inet-ban" {
|
|
||||||
// ban action
|
|
||||||
target := ev.Target()
|
target := ev.Target()
|
||||||
if target[0] == '[' {
|
switch action {
|
||||||
// probably a literal ipv6 rangeban
|
case ModDeleteAlt:
|
||||||
if mod.AllowBan(pubkey) {
|
case ModDelete:
|
||||||
err := mod.BanAddress(target)
|
if mod.AllowDelete(pubkey, target) {
|
||||||
if err != nil {
|
mod.Do(ev)
|
||||||
log.Println("failed to do literal ipv6 range ban on", target, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Println("ignoring literal ipv6 rangeban from", pubkey, "as they are not allowed to ban")
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
case ModInetBan:
|
||||||
parts := strings.Split(target, ":")
|
|
||||||
if len(parts) == 3 {
|
|
||||||
// encrypted ip
|
|
||||||
encaddr, key := parts[0], parts[1]
|
|
||||||
cidr := decAddr(encaddr, key)
|
|
||||||
if cidr == "" {
|
|
||||||
log.Println("failed to decrypt inet ban")
|
|
||||||
} else if mod.AllowBan(pubkey) {
|
|
||||||
err := mod.BanAddress(cidr)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("failed to do range ban on", cidr, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Println("ingoring encrypted-ip inet ban from", pubkey, "as they are not allowed to ban")
|
|
||||||
}
|
|
||||||
} else if len(parts) == 2 {
|
|
||||||
// x-encrypted-ip ban without pad
|
|
||||||
if mod.AllowBan(pubkey) {
|
if mod.AllowBan(pubkey) {
|
||||||
err := mod.database.BanEncAddr(parts[0])
|
mod.Do(ev)
|
||||||
if err != nil {
|
|
||||||
log.Println("failed to ban encrypted ip", err)
|
|
||||||
}
|
}
|
||||||
} else {
|
return
|
||||||
log.Println("ignoring encrypted-ip ban from", pubkey, "as they are not allowed to ban")
|
case ModHide:
|
||||||
|
case ModLock:
|
||||||
|
case ModSage:
|
||||||
|
case ModStick:
|
||||||
|
case ModRemoveAttachment:
|
||||||
|
if mod.AllowJanitor(pubkey) {
|
||||||
|
mod.Do(ev)
|
||||||
}
|
}
|
||||||
} else if len(parts) == 1 {
|
default:
|
||||||
// literal cidr
|
// invalid action
|
||||||
cidr := parts[0]
|
|
||||||
if mod.AllowBan(pubkey) {
|
|
||||||
err := mod.BanAddress(cidr)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("failed to do literal range ban on", cidr, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Println("ingoring literal cidr range ban from", pubkey, "as they are not allowed to ban")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("invalid overchan-inet-ban: target=%s", target)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Println("invalid mod action", action, "from", pubkey)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user