version 0.2.16
[fms.git] / src / nntp / nntpconnection.cpp
index 078c1c3..54d7c94 100644 (file)
@@ -6,6 +6,7 @@
 #include "../../include/message.h"\r
 #include "../../include/messagelist.h"\r
 #include "../../include/option.h"\r
+#include "../../include/nntp/extensiontrust.h"\r
 \r
 #include <algorithm>\r
 \r
@@ -28,6 +29,7 @@ NNTPConnection::NNTPConnection(SOCKET sock)
        m_status.m_boardid=-1;\r
        m_status.m_messageid=-1;\r
        m_status.m_mode=MODE_NONE;\r
+       m_status.m_authenticated=false;\r
 \r
        Option::Instance()->Get("NNTPAllowPost",tempval);\r
        if(tempval=="true")\r
@@ -68,6 +70,58 @@ const bool NNTPConnection::HandleArticleCommand(const NNTPCommand &command)
        return true;\r
 }\r
 \r
+const bool NNTPConnection::HandleAuthInfoCommand(const NNTPCommand &command)\r
+{\r
+       if(command.m_arguments.size()<2)\r
+       {\r
+               SendBufferedLine("501 Syntax error");\r
+       }\r
+       else if(m_status.m_authenticated==true)\r
+       {\r
+               SendBufferedLine("502 Command unavailable");            // not available when already authenticated\r
+       }\r
+       else\r
+       {\r
+               std::string arg=command.m_arguments[0];\r
+               StringFunctions::UpperCase(arg,arg);\r
+               std::string name="";\r
+               // get remaining args as part of the name since a name might have a space and the args are split on spaces\r
+               for(std::vector<std::string>::const_iterator i=command.m_arguments.begin()+1; i!=command.m_arguments.end(); i++)\r
+               {\r
+                       // we split on the space, so add it back\r
+                       if(i!=command.m_arguments.begin()+1)\r
+                       {\r
+                               name+=" ";\r
+                       }       \r
+                       name+=(*i);\r
+               }\r
+               if(arg=="USER")\r
+               {\r
+                       LocalIdentity localid;\r
+                       if(localid.Load(name))\r
+                       {\r
+                               m_status.m_authuser=localid;\r
+                               m_status.m_authenticated=true;\r
+                               SendBufferedLine("281 Authentication accepted");\r
+                       }\r
+                       else\r
+                       {\r
+                               SendBufferedLine("481 Authentication failed");\r
+                       }\r
+               }\r
+               else if(arg=="PASS")\r
+               {\r
+                       SendBufferedLine("482 Authentication commands issued out of sequence"); // only require username\r
+               }\r
+               else\r
+               {\r
+                       SendBufferedLine("501 Syntax error");\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
 const bool NNTPConnection::HandleBodyCommand(const NNTPCommand &command)\r
 {\r
        SendArticleParts(command);\r
@@ -80,7 +134,10 @@ const bool NNTPConnection::HandleCapabilitiesCommand(const NNTPCommand &command)
        \r
        SendBufferedLine("101 Capability list :");\r
        SendBufferedLine("VERSION 2");\r
-       SendBufferedLine("MODE-READER");\r
+       if(m_status.m_authenticated==false)             // RFC 4643 2.2 0 - don't advertise MODE-READER after authentication\r
+       {\r
+               SendBufferedLine("MODE-READER");\r
+       }\r
        SendBufferedLine("READER");\r
        SendBufferedLine("LIST OVERVIEW.FMT");\r
        SendBufferedLine("OVER MSGID");\r
@@ -88,6 +145,11 @@ const bool NNTPConnection::HandleCapabilitiesCommand(const NNTPCommand &command)
        {\r
                SendBufferedLine("POST");\r
        }\r
+       if(m_status.m_authenticated==false)\r
+       {\r
+               SendBufferedLine("AUTHINFO USER");\r
+       }\r
+       SendBufferedLine("XFMSTRUST");\r
        SendBufferedLine(".");\r
        \r
        return true;\r
@@ -163,6 +225,22 @@ const bool NNTPConnection::HandleCommand(const NNTPCommand &command)
        {\r
                return HandleOverCommand(command);\r
        }\r
+       if(command.m_command=="AUTHINFO")\r
+       {\r
+               return HandleAuthInfoCommand(command);\r
+       }\r
+       if(command.m_command=="XGETTRUST")\r
+       {\r
+               return HandleGetTrustCommand(command);\r
+       }\r
+       if(command.m_command=="XSETTRUST")\r
+       {\r
+               return HandleSetTrustCommand(command);\r
+       }\r
+       if(command.m_command=="XGETTRUSTLIST")\r
+       {\r
+               return HandleGetTrustListCommand(command);\r
+       }\r
 \r
        return false;\r
 }\r
@@ -175,6 +253,120 @@ const bool NNTPConnection::HandleDateCommand(const NNTPCommand &command)
        return true;\r
 }\r
 \r
+const bool NNTPConnection::HandleGetTrustCommand(const NNTPCommand &command)\r
+{\r
+       if(command.m_arguments.size()>=2)\r
+       {\r
+               std::string type=command.m_arguments[0];\r
+               StringFunctions::UpperCase(type,type);\r
+               if(type=="MESSAGE" || type=="TRUSTLIST")\r
+               {\r
+                       if(m_status.m_authenticated)\r
+                       {\r
+                               bool found=false;\r
+                               int trust=-1;\r
+                               std::string nntpname="";\r
+                               for(int i=1; i<command.m_arguments.size(); i++)\r
+                               {\r
+                                       nntpname+=command.m_arguments[i];\r
+                               }\r
+\r
+                               TrustExtension tr(m_status.m_authuser.GetID());\r
+\r
+                               if(type=="MESSAGE")\r
+                               {\r
+                                       if(tr.GetMessageTrust(nntpname,trust))\r
+                                       {\r
+                                               found=true;\r
+                                       }\r
+                               }\r
+                               if(type=="TRUSTLIST")\r
+                               {\r
+                                       if(tr.GetTrustListTrust(nntpname,trust))\r
+                                       {\r
+                                               found=true;\r
+                                       }\r
+                               }\r
+\r
+                               if(trust>=0 && found)\r
+                               {\r
+                                       std::string truststr="";\r
+                                       StringFunctions::Convert(trust,truststr);\r
+                                       SendBufferedLine("280 "+truststr);\r
+                               }\r
+                               else if(found)\r
+                               {\r
+                                       SendBufferedLine("281 null");\r
+                               }\r
+                               else\r
+                               {\r
+                                       SendBufferedLine("480 Identity not found");\r
+                               }\r
+\r
+                       }\r
+                       else\r
+                       {\r
+                               SendBufferedLine("480 User not authenticated");\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       SendBufferedLine("501 Syntax error");\r
+               }\r
+       }\r
+       else\r
+       {\r
+               SendBufferedLine("501 Syntax error");\r
+       }\r
+       return true;\r
+}      \r
+\r
+const bool NNTPConnection::HandleGetTrustListCommand(const NNTPCommand &command)\r
+{\r
+       if(m_status.m_authenticated)\r
+       {\r
+               TrustExtension tr(m_status.m_authuser.GetID());\r
+               std::map<std::string,std::pair<int,int> > trustlist;\r
+               if(tr.GetTrustList(trustlist))\r
+               {\r
+                       SendBufferedLine("280 Trust list follows");\r
+                       for(std::map<std::string,std::pair<int,int> >::iterator i=trustlist.begin(); i!=trustlist.end(); i++)\r
+                       {\r
+                               std::ostringstream tempstr;\r
+                               tempstr << (*i).first << "\t";\r
+                               if((*i).second.first>-1)\r
+                               {\r
+                                       tempstr << (*i).second.first;\r
+                               } \r
+                               else\r
+                               {\r
+                                       tempstr << "null";\r
+                               }\r
+                               tempstr << "\t";\r
+                               if((*i).second.second>-1)\r
+                               {\r
+                                       tempstr << (*i).second.second;\r
+                               }\r
+                               else\r
+                               {\r
+                                       tempstr << "null";\r
+                               }\r
+                               SendBufferedLine(tempstr.str());\r
+                       }\r
+                       SendBufferedLine(".");\r
+               }\r
+               else\r
+               {\r
+                       SendBufferedLine("501 Syntax error");\r
+               }\r
+       }\r
+       else\r
+       {\r
+               SendBufferedLine("480 User not authenticated");\r
+       }\r
+       return true;\r
+}\r
+\r
 const bool NNTPConnection::HandleGroupCommand(const NNTPCommand &command)\r
 {\r
        if(command.m_arguments.size()==1)\r
@@ -317,7 +509,7 @@ const bool NNTPConnection::HandleListCommand(const NNTPCommand &command)
                                show=uwildmat((*i).GetBoardName().c_str(),arg2.c_str());\r
                        }\r
 \r
-                       if(show==true)\r
+                       if(show==true && (*i).GetSaveReceivedMessages()==true)\r
                        {\r
                                tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << (m_status.m_allowpost ? "y" : "n");\r
                                SendBufferedLine(tempstr.str());\r
@@ -348,7 +540,7 @@ const bool NNTPConnection::HandleListCommand(const NNTPCommand &command)
                                show=uwildmat((*i).GetBoardName().c_str(),arg2.c_str());\r
                        }\r
 \r
-                       if(show==true)\r
+                       if(show==true && (*i).GetSaveReceivedMessages()==true)\r
                        {\r
                                tempstr << (*i).GetBoardName() << "\t" << (*i).GetBoardDescription();\r
                                SendBufferedLine(tempstr.str());\r
@@ -559,9 +751,12 @@ const bool NNTPConnection::HandleNewGroupsCommand(const NNTPCommand &command)
 \r
                for(BoardList::iterator i=bl.begin(); i!=bl.end(); i++)\r
                {\r
-                       std::ostringstream tempstr;\r
-                       tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << m_status.m_allowpost ? "y" : "n";\r
-                       SendBufferedLine(tempstr.str());\r
+                       if((*i).GetSaveReceivedMessages()==true)\r
+                       {\r
+                               std::ostringstream tempstr;\r
+                               tempstr << (*i).GetBoardName() << " " << (*i).GetHighMessageID() << " " << (*i).GetLowMessageID() << " " << m_status.m_allowpost ? "y" : "n";\r
+                               SendBufferedLine(tempstr.str());\r
+                       }\r
                }\r
 \r
                SendBufferedLine(".");\r
@@ -780,15 +975,24 @@ void NNTPConnection::HandlePostedMessage(const std::string &message)
 \r
        if(mess.ParseNNTPMessage(message))\r
        {\r
+               // if we authenticated, set the username to the authenticated user\r
+               if(m_status.m_authenticated)\r
+               {\r
+                       mess.SetFromName(m_status.m_authuser.GetName());\r
+               }\r
+               // handle a messages posted to an adminboard\r
                if(mess.PostedToAdministrationBoard()==true)\r
                {\r
                        mess.HandleAdministrationMessage();\r
                }\r
+               if(mess.StartFreenetInsert())\r
+               {\r
+                       SendBufferedLine("240 Article received OK");\r
+               }\r
                else\r
                {\r
-                       mess.StartFreenetInsert();\r
+                       SendBufferedLine("441 Posting failed.  Make sure the identity you are sending with exists!");\r
                }\r
-               SendBufferedLine("240 Article received OK");\r
        }\r
        else\r
        {\r
@@ -862,6 +1066,83 @@ void NNTPConnection::HandleReceivedData()
        }\r
 }\r
 \r
+const bool NNTPConnection::HandleSetTrustCommand(const NNTPCommand &command)\r
+{\r
+       if(command.m_arguments.size()>=3)\r
+       {\r
+               std::string type=command.m_arguments[0];\r
+               StringFunctions::UpperCase(type,type);\r
+               if(type=="MESSAGE" || type=="TRUSTLIST")\r
+               {\r
+                       if(m_status.m_authenticated)\r
+                       {\r
+                               bool found=false;\r
+                               bool valid=false;\r
+                               int trust=-1;\r
+                               std::string nntpname="";\r
+                               for(int i=1; i<command.m_arguments.size()-1; i++)\r
+                               {\r
+                                       nntpname+=command.m_arguments[i];\r
+                               }\r
+\r
+                               if(command.m_arguments[command.m_arguments.size()-1]!="null")\r
+                               {\r
+                                       StringFunctions::Convert(command.m_arguments[command.m_arguments.size()-1],trust);\r
+                               }\r
+\r
+                               if(trust>=-1 && trust<=100)\r
+                               {\r
+                                       valid=true;\r
+                               }\r
+\r
+                               TrustExtension tr(m_status.m_authuser.GetID());\r
+\r
+                               if(type=="MESSAGE")\r
+                               {\r
+                                       if(tr.SetMessageTrust(nntpname,trust))\r
+                                       {\r
+                                               found=true;\r
+                                       }\r
+                               }\r
+                               if(type=="TRUSTLIST")\r
+                               {\r
+                                       if(tr.SetTrustListTrust(nntpname,trust))\r
+                                       {\r
+                                               found=true;\r
+                                       }\r
+                               }\r
+\r
+                               if(found && valid)\r
+                               {\r
+                                       SendBufferedLine("280 Trust Set");\r
+                               }\r
+                               else if(found==false)\r
+                               {\r
+                                       SendBufferedLine("480 Identity not found");\r
+                               }\r
+                               else\r
+                               {\r
+                                       SendBufferedLine("501 Syntax error");\r
+                               }\r
+\r
+                       }\r
+                       else\r
+                       {\r
+                               SendBufferedLine("480 User not authenticated");\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       SendBufferedLine("501 Syntax error");\r
+               }\r
+       }\r
+       else\r
+       {\r
+               SendBufferedLine("501 Syntax error");\r
+       }\r
+       return true;\r
+}\r
+\r
 const bool NNTPConnection::HandleStatCommand(const NNTPCommand &command)\r
 {\r
        SendArticleParts(command);\r