src/datetime.cpp\r
src/global.cpp\r
src/hex.cpp\r
+src/localidentity.cpp\r
src/logfile.cpp\r
src/main.cpp\r
src/message.cpp\r
#include <vector>\r
#include "pthreadwrapper/thread.h"\r
\r
-#define FMS_VERSION "0.2.8"\r
+#define FMS_VERSION "0.2.9"\r
\r
// opens database and creates tables and initial inserts if necessary\r
void SetupDB();\r
--- /dev/null
+#ifndef _localidentity_\r
+#define _localidentity_\r
+\r
+#include "idatabase.h"\r
+\r
+class LocalIdentity:public IDatabase\r
+{\r
+public:\r
+ LocalIdentity();\r
+\r
+ const bool Load(const int id);\r
+ const bool Load(const std::string &name);\r
+\r
+ const int GetID() const { return m_id; }\r
+ const std::string GetName() const { return m_name; }\r
+ const std::string GetPublicKey() const { return m_publickey; }\r
+ const std::string GetPrivateKey() const { return m_privatekey; }\r
+\r
+private:\r
+ void Initialize();\r
+\r
+ int m_id;\r
+ std::string m_name;\r
+ std::string m_publickey;\r
+ std::string m_privatekey;\r
+};\r
+\r
+#endif // _localidentity_\r
std::vector<std::string> GetBoards() const { return m_boards; }\r
std::map<long,std::string> GetInReplyTo() const { return m_inreplyto; }\r
\r
+ void SetFromName(const std::string &fromname) { m_fromname=fromname; }\r
+\r
const std::string GetNNTPHeaders() const;\r
const std::string GetNNTPArticleID() const;\r
const std::string GetNNTPBody() const;\r
#include "../socketdefines.h"\r
#include "../ilogger.h"\r
#include "../message.h"\r
+#include "../localidentity.h"\r
\r
#include <string>\r
#include <vector>\r
bool m_isposting;\r
long m_boardid;\r
long m_messageid;\r
+ LocalIdentity m_authuser; // -1 if user not authenticated, otherwise id of user from tblLocalIdentity\r
+ bool m_authenticated;\r
};\r
\r
void SendBuffered(const std::string &data);\r
const bool HandleNewGroupsCommand(const NNTPCommand &command);\r
const bool HandlePostCommand(const NNTPCommand &command);\r
const bool HandleOverCommand(const NNTPCommand &command);\r
+ const bool HandleAuthInfoCommand(const NNTPCommand &command);\r
\r
SOCKET m_socket;\r
ClientStatus m_status;\r
{\r
std::vector<char> invec(input.begin(),input.end());\r
std::vector<char> outvec(invec.size()*4,0);\r
-#ifdef _WIN32\r
+#if defined(_WIN32) || defined(__APPLE__) || defined(__DARWIN__)\r
const char *inptr=&invec[0];\r
#else\r
char *inptr=&invec[0];\r
// TODO remove sometime after 0.1.17\r
FixCapitalBoardNames();\r
\r
+ // run analyze - may speed up some queries\r
+ db->Execute("ANALYZE;");\r
+\r
}\r
\r
void ConvertDB0100To0101()\r
--- /dev/null
+#include "../include/localidentity.h"\r
+\r
+#ifdef XMEM\r
+ #include <xmem.h>\r
+#endif\r
+\r
+LocalIdentity::LocalIdentity()\r
+{\r
+ Initialize();\r
+}\r
+\r
+void LocalIdentity::Initialize()\r
+{\r
+ m_id=-1;\r
+ m_name="";\r
+ m_publickey="";\r
+ m_privatekey=""; \r
+}\r
+\r
+const bool LocalIdentity::Load(const int id)\r
+{\r
+\r
+ Initialize();\r
+\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID,Name,PublicKey,PrivateKey FROM tblLocalIdentity WHERE LocalIdentityID=?;");\r
+ st.Bind(0,id);\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ st.ResultInt(0,m_id);\r
+ st.ResultText(1,m_name);\r
+ st.ResultText(2,m_publickey);\r
+ st.ResultText(3,m_privatekey);\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+\r
+}\r
+\r
+const bool LocalIdentity::Load(const std::string &name)\r
+{\r
+ Initialize();\r
+\r
+ SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID FROM tblLocalIdentity WHERE Name=?;");\r
+ st.Bind(0,name);\r
+ st.Step();\r
+ if(st.RowReturned())\r
+ {\r
+ int id=-1;\r
+ st.ResultInt(0,id);\r
+ return Load(id);\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+}
\ No newline at end of file
st.Step();\r
if(st.RowReturned())\r
{\r
+ if(m_replyboardname==(*i))\r
+ {\r
+ m_replyboardname="";\r
+ }\r
i=m_boards.erase(i);\r
}\r
else\r
}\r
st.Reset();\r
}\r
+ if(m_replyboardname=="" && m_boards.begin()!=m_boards.end())\r
+ {\r
+ m_replyboardname=(*m_boards.begin());\r
+ }\r
}\r
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
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
\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
{\r
SendBufferedLine("POST");\r
}\r
+ if(m_status.m_authenticated==false)\r
+ {\r
+ SendBufferedLine("AUTHINFO USER");\r
+ }\r
SendBufferedLine(".");\r
\r
return true;\r
{\r
return HandleOverCommand(command);\r
}\r
+ if(command.m_command=="AUTHINFO")\r
+ {\r
+ return HandleAuthInfoCommand(command);\r
+ }\r
\r
return false;\r
}\r
\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
sock=socket(current->ai_family,current->ai_socktype,current->ai_protocol);\r
if(sock!=INVALID_SOCKET)\r
{\r
+ #ifndef _WIN32\r
+ const char optval='1';\r
+ setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&optval,1);\r
+ #endif\r
if(bind(sock,current->ai_addr,current->ai_addrlen)==0)\r
{\r
if(listen(sock,10)==0)\r