some NNTP improvements
This commit is contained in:
parent
8cb044a5e3
commit
337a61dd7f
@ -382,18 +382,19 @@ func (self *nntpConnection) handleStreaming(daemon *NNTPDaemon, conn *textproto.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we want the article given its mime header
|
// check if we want the article given its auth status and mime header
|
||||||
// returns empty string if it's okay otherwise an error message
|
// returns empty string if it's okay otherwise an error message
|
||||||
func (self *nntpConnection) checkMIMEHeader(daemon *NNTPDaemon, h map[string][]string) (reason string, allow bool, err error) {
|
func (self *nntpConnection) checkMIMEHeader(daemon *NNTPDaemon, hdr textproto.MIMEHeader) (reason string, allow bool, err error) {
|
||||||
if !self.authenticated {
|
if !self.authenticated {
|
||||||
reason = "not authenticated"
|
reason = "not authenticated"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hdr := textproto.MIMEHeader(h)
|
|
||||||
reason, allow, err = self.checkMIMEHeaderNoAuth(daemon, hdr)
|
reason, allow, err = self.checkMIMEHeaderNoAuth(daemon, hdr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if we want the article given its mime header without checking auth status
|
||||||
|
// returns empty string if it's okay otherwise an error message
|
||||||
func (self *nntpConnection) checkMIMEHeaderNoAuth(daemon *NNTPDaemon, hdr textproto.MIMEHeader) (reason string, ban bool, err error) {
|
func (self *nntpConnection) checkMIMEHeaderNoAuth(daemon *NNTPDaemon, hdr textproto.MIMEHeader) (reason string, ban bool, err error) {
|
||||||
newsgroup := hdr.Get("Newsgroups")
|
newsgroup := hdr.Get("Newsgroups")
|
||||||
reference := hdr.Get("References")
|
reference := hdr.Get("References")
|
||||||
@ -664,9 +665,9 @@ func (self *nntpConnection) handleLine(daemon *NNTPDaemon, code int, line string
|
|||||||
} else if cmd == "CHECK" {
|
} else if cmd == "CHECK" {
|
||||||
// handle check command
|
// handle check command
|
||||||
msgid := parts[1]
|
msgid := parts[1]
|
||||||
if self.mode != "STREAM" {
|
if !self.authenticated {
|
||||||
// we can't we are not in streaming mode
|
// if client cannot TAKETHIS it shouldn't be able to CHECK either
|
||||||
conn.PrintfLine("431 %s", msgid)
|
conn.PrintfLine("480 You have not authenticated")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// have we seen this article?
|
// have we seen this article?
|
||||||
@ -682,25 +683,48 @@ func (self *nntpConnection) handleLine(daemon *NNTPDaemon, code int, line string
|
|||||||
}
|
}
|
||||||
} else if cmd == "TAKETHIS" {
|
} else if cmd == "TAKETHIS" {
|
||||||
// handle takethis command
|
// handle takethis command
|
||||||
|
r := bufio.NewReader(conn.DotReader())
|
||||||
|
if !self.authenticated {
|
||||||
|
// early reject without parsing incase client not allowed to post
|
||||||
|
// send response first to allow client to stop sending
|
||||||
|
// XXX what happens if our send queue is full and this blocks?
|
||||||
|
// other side will probably fill up sending article to us
|
||||||
|
// async receive processing would help there
|
||||||
|
// but this situation has low likehood to happen
|
||||||
|
// operating system/transport buffering will compensate
|
||||||
|
// so leave it this way
|
||||||
|
conn.PrintfLine("480 You have not authenticated")
|
||||||
|
// discard whole article without looking at insides
|
||||||
|
// it should be dot-terminated either way
|
||||||
|
_, err = io.Copy(ioutil.Discard, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// client is allowed to post
|
||||||
var msg *mail.Message
|
var msg *mail.Message
|
||||||
var reason string
|
var reason string
|
||||||
var ban bool
|
var ban bool
|
||||||
// read the article header
|
// read the article header
|
||||||
r := bufio.NewReader(conn.DotReader())
|
|
||||||
msg, err = readMIMEHeader(r)
|
msg, err = readMIMEHeader(r)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
|
log.Println(self.name, "error reading mime header:", err)
|
||||||
|
conn.PrintfLine("439 %s error reading mime header", msgid)
|
||||||
|
// if reading header error'd, msg.Body wont be set
|
||||||
|
_, err = io.Copy(ioutil.Discard, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
hdr := textproto.MIMEHeader(msg.Header)
|
hdr := textproto.MIMEHeader(msg.Header)
|
||||||
// check the header
|
// check the header
|
||||||
reason, ban, err = self.checkMIMEHeader(daemon, hdr)
|
reason, ban, err = self.checkMIMEHeaderNoAuth(daemon, hdr)
|
||||||
if len(reason) > 0 {
|
if len(reason) > 0 {
|
||||||
// discard, we do not want
|
// discard, we do not want
|
||||||
code = 439
|
|
||||||
log.Println(self.name, "rejected", msgid, reason)
|
log.Println(self.name, "rejected", msgid, reason)
|
||||||
|
conn.PrintfLine("439 %s %s", code, msgid, reason)
|
||||||
_, err = io.Copy(ioutil.Discard, msg.Body)
|
_, err = io.Copy(ioutil.Discard, msg.Body)
|
||||||
if ban {
|
if ban {
|
||||||
err = daemon.database.BanArticle(msgid, reason)
|
err = daemon.database.BanArticle(msgid, reason)
|
||||||
}
|
}
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
|
// looks good to accept
|
||||||
// check if we don't have the rootpost
|
// check if we don't have the rootpost
|
||||||
reference := hdr.Get("References")
|
reference := hdr.Get("References")
|
||||||
if reference != "" && ValidMessageID(reference) && !daemon.store.HasArticle(reference) && !daemon.database.IsExpired(reference) {
|
if reference != "" && ValidMessageID(reference) && !daemon.store.HasArticle(reference) && !daemon.database.IsExpired(reference) {
|
||||||
@ -715,22 +739,17 @@ func (self *nntpConnection) handleLine(daemon *NNTPDaemon, code int, line string
|
|||||||
code = 439
|
code = 439
|
||||||
reason = err.Error()
|
reason = err.Error()
|
||||||
}
|
}
|
||||||
|
conn.PrintfLine("%d %s %s", code, msgid, reason)
|
||||||
} else {
|
} else {
|
||||||
// error?
|
// error?
|
||||||
// discard, we do not want
|
// discard, we do not want
|
||||||
code = 439
|
log.Println(self.name, "rejected", msgid, "unexpected error", err)
|
||||||
log.Println(self.name, "rejected", msgid, reason)
|
conn.PrintfLine("439 %s unexpected error", msgid)
|
||||||
_, err = io.Copy(ioutil.Discard, msg.Body)
|
_, err = io.Copy(ioutil.Discard, msg.Body)
|
||||||
if ban {
|
if ban {
|
||||||
err = daemon.database.BanArticle(msgid, reason)
|
err = daemon.database.BanArticle(msgid, reason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log.Println(self.name, "error reading mime header:", err)
|
|
||||||
code = 439
|
|
||||||
reason = "error reading mime header"
|
|
||||||
}
|
|
||||||
conn.PrintfLine("%d %s %s", code, msgid, reason)
|
|
||||||
} else if cmd == "ARTICLE" {
|
} else if cmd == "ARTICLE" {
|
||||||
if !ValidMessageID(msgid) {
|
if !ValidMessageID(msgid) {
|
||||||
if len(self.group) > 0 {
|
if len(self.group) > 0 {
|
||||||
@ -759,7 +778,7 @@ func (self *nntpConnection) handleLine(daemon *NNTPDaemon, code int, line string
|
|||||||
}
|
}
|
||||||
} else if cmd == "IHAVE" {
|
} else if cmd == "IHAVE" {
|
||||||
if !self.authenticated {
|
if !self.authenticated {
|
||||||
conn.PrintfLine("483 You have not authenticated")
|
conn.PrintfLine("480 You have not authenticated")
|
||||||
} else {
|
} else {
|
||||||
// handle IHAVE command
|
// handle IHAVE command
|
||||||
msgid := parts[1]
|
msgid := parts[1]
|
||||||
@ -1656,7 +1675,6 @@ func (self *nntpConnection) runConnection(daemon *NNTPDaemon, inbound, stream, r
|
|||||||
conn.PrintfLine("203 Stream it brah")
|
conn.PrintfLine("203 Stream it brah")
|
||||||
self.mode = "STREAM"
|
self.mode = "STREAM"
|
||||||
log.Println(self.name, "streaming enabled")
|
log.Println(self.name, "streaming enabled")
|
||||||
go self.startStreaming(daemon, reader, conn)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user