SMTPSvr.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:121k
源码类别:

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "SvrDefines.h"
  25. #include "SList.h"
  26. #include "ShBlocks.h"
  27. #include "BuffSock.h"
  28. #include "ResLocks.h"
  29. #include "StrUtils.h"
  30. #include "UsrUtils.h"
  31. #include "SvrUtils.h"
  32. #include "MessQueue.h"
  33. #include "SMAILUtils.h"
  34. #include "QueueUtils.h"
  35. #include "MiscUtils.h"
  36. #include "Base64Enc.h"
  37. #include "MD5.h"
  38. #include "UsrMailList.h"
  39. #include "SMTPSvr.h"
  40. #include "SMTPUtils.h"
  41. #include "MailDomains.h"
  42. #include "POP3Utils.h"
  43. #include "Filter.h"
  44. #include "MailConfig.h"
  45. #include "AppDefines.h"
  46. #include "MailSvr.h"
  47. #define SMTP_MAX_LINE_SIZE      2048
  48. #define SMTPSRV_ACCEPT_TIMEOUT  4
  49. #define STD_SMTP_TIMEOUT        30
  50. #define SMTP_LISTEN_SIZE        64
  51. #define SMTP_WAIT_SLEEP         2
  52. #define MAX_CLIENTS_WAIT        300
  53. #define SMTP_IPMAP_FILE         "smtp.ipmap.tab"
  54. #define SMTP_IPPROP_FILE        "smtp.ipprop.tab"
  55. #define SMTP_LOG_FILE           "smtp"
  56. #define SMTP_SERVER_NAME        "[" APP_NAME_VERSION_STR " ESMTP Server]"
  57. #define SMTP_PRE_DATA_FILTER    "pre-data"
  58. #define SMTP_POST_DATA_FILTER   "post-data"
  59. #define SMTP_FILTER_REJECT_CODE 3
  60. #define PLAIN_AUTH_PARAM_SIZE   1024
  61. #define LOGIN_AUTH_USERNAME     "Username:"
  62. #define LOGIN_AUTH_PASSWORD     "Password:"
  63. #define SVR_SMTP_AUTH_FILE      "smtpauth.tab"
  64. #define SVR_SMTPAUTH_LINE_MAX   512
  65. #define SVR_SMTP_EXTAUTH_FILE   "smtpextauth.tab"
  66. #define SVR_SMTP_EXTAUTH_LINE_MAX   1024
  67. #define SVR_SMTP_EXTAUTH_TIMEOUT    60
  68. #define SVR_SMTP_EXTAUTH_PRIORITY   SYS_PRIORITY_NORMAL
  69. #define SVR_SMTP_EXTAUTH_SUCCESS    0
  70. #define SMTPF_RELAY_ENABLED     (1 << 0)
  71. #define SMTPF_MAIL_LOCKED       (1 << 1)
  72. #define SMTPF_MAIL_UNLOCKED     (1 << 2)
  73. #define SMTPF_AUTHENTICATED     (1 << 3)
  74. #define SMTPF_VRFY_ENABLED      (1 << 4)
  75. #define SMTPF_MAPPED_IP         (1 << 5)
  76. #define SMTPF_NORDNS_IP         (1 << 6)
  77. #define SMTPF_ETRN_ENABLED      (1 << 7)
  78. #define SMTPF_NOEMIT_AUTH       (1 << 8)
  79. #define SMTPF_WHITE_LISTED      (1 << 9)
  80. #define SMTPF_BLOCKED_IP        (1 << 10)
  81. #define SMTPF_STATIC_MASK       (SMTPF_MAPPED_IP | SMTPF_NORDNS_IP | SMTPF_WHITE_LISTED | SMTPF_BLOCKED_IP)
  82. #define SMTPF_AUTH_MASK         (SMTPF_RELAY_ENABLED | SMTPF_MAIL_UNLOCKED | SMTPF_AUTHENTICATED | 
  83.                                         SMTPF_VRFY_ENABLED | SMTPF_ETRN_ENABLED)
  84. #define SMTPF_RESET_MASK        (SMTPF_AUTH_MASK | SMTPF_STATIC_MASK | SMTPF_NOEMIT_AUTH)
  85. #define SMTP_FILTER_FL_BREAK    (1 << 4)
  86. #define SMTP_FILTER_FL_MASK     SMTP_FILTER_FL_BREAK
  87. enum SMTPStates {
  88. stateInit = 0,
  89. stateHelo,
  90. stateAuthenticated,
  91. stateMail,
  92. stateRcpt,
  93. stateExit
  94. };
  95. struct SMTPSession {
  96. int iSMTPState;
  97. SHB_HANDLE hShbSMTP;
  98. SMTPConfig *pSMTPCfg;
  99. SVRCFG_HANDLE hSvrConfig;
  100. SYS_INET_ADDR PeerInfo;
  101. SYS_INET_ADDR SockInfo;
  102. int iCmdDelay;
  103. unsigned long ulMaxMsgSize;
  104. char szSvrFQDN[MAX_ADDR_NAME];
  105. char szSvrDomain[MAX_ADDR_NAME];
  106. char szClientFQDN[MAX_ADDR_NAME];
  107. char szClientDomain[MAX_ADDR_NAME];
  108. char szDestDomain[MAX_ADDR_NAME];
  109. char szLogonUser[128];
  110. char szMsgFile[SYS_MAX_PATH];
  111. FILE *pMsgFile;
  112. char *pszFrom;
  113. char *pszRcpt;
  114. char *pszSendRcpt;
  115. int iRcptCount;
  116. int iErrorsCount;
  117. int iErrorsMax;
  118. SYS_UINT64 ullMessageID;
  119. char szMessageID[128];
  120. char szTimeStamp[256];
  121. unsigned long ulSetupFlags;
  122. unsigned long ulFlags;
  123. char *pszCustMsg;
  124. char szRejMapName[256];
  125. };
  126. enum SmtpAuthFields {
  127. smtpaUsername = 0,
  128. smtpaPassword,
  129. smtpaPerms,
  130. smtpaMax
  131. };
  132. static SMTPConfig *SMTPGetConfigCopy(SHB_HANDLE hShbSMTP);
  133. static int SMTPLogEnabled(SHB_HANDLE hShbSMTP, SMTPConfig * pSMTPCfg = NULL);
  134. static int SMTPCheckPeerIP(SYS_SOCKET SockFD);
  135. static int SMTPThreadCountAdd(long lCount, SHB_HANDLE hShbSMTP, SMTPConfig * pSMTPCfg = NULL);
  136. static unsigned int SMTPClientThread(void *pThreadData);
  137. static int SMTPCheckSysResources(SVRCFG_HANDLE hSvrConfig);
  138. static int SMTPCheckMapsList(SYS_INET_ADDR const &PeerInfo, char const *pszMapList,
  139.      char *pszMapName, int iMaxMapName, int &iMapCode);
  140. static int SMTPApplyIPProps(SMTPSession & SMTPS);
  141. static int SMTPDoIPBasedInit(SMTPSession & SMTPS, char *&pszSMTPError);
  142. static int SMTPInitSession(SHB_HANDLE hShbSMTP, BSOCK_HANDLE hBSock,
  143.    SMTPSession & SMTPS, char *&pszSMTPError);
  144. static int SMTPLoadConfig(SMTPSession & SMTPS, char const *pszSvrConfig);
  145. static int SMTPApplyPerms(SMTPSession & SMTPS, char const *pszPerms);
  146. static int SMTPApplyUserConfig(SMTPSession & SMTPS, UserInfo * pUI);
  147. static int SMTPLogSession(SMTPSession & SMTPS, char const *pszSender,
  148.   char const *pszRecipient, char const *pszStatus,
  149.   unsigned long ulMsgSize);
  150. static int SMTPSendError(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszFormat, ...);
  151. static int SMTPHandleSession(SHB_HANDLE hShbSMTP, BSOCK_HANDLE hBSock);
  152. static void SMTPClearSession(SMTPSession & SMTPS);
  153. static void SMTPResetSession(SMTPSession & SMTPS);
  154. static int SMTPHandleCommand(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  155. static int SMTPCheckReturnPath(const char *pszCommand, char **ppszRetDomains,
  156.        SMTPSession & SMTPS, char *&pszSMTPError);
  157. static int SMTPTryPopAuthIpCheck(SMTPSession & SMTPS, char const *pszUser, char const *pszDomain);
  158. static int SMTPAddMessageInfo(SMTPSession & SMTPS);
  159. static int SMTPCheckMailParams(const char *pszCommand, char **ppszRetDomains,
  160.        SMTPSession & SMTPS, char *&pszSMTPError);
  161. static int SMTPHandleCmd_MAIL(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  162. static int SMTPCheckRelayCapability(SMTPSession & SMTPS, char const *pszDestDomain);
  163. static int SMTPCheckForwardPath(char **ppszFwdDomains, SMTPSession & SMTPS,
  164. char *&pszRealRcpt, char *&pszSMTPError);
  165. static int SMTPHandleCmd_RCPT(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  166. static int SMTPGetFilterFile(const char *pszFiltID, char *pszFileName, int iMaxName);
  167. static int SMTPFilterMacroSubstitutes(char **ppszCmdTokens, SMTPSession & SMTPS);
  168. static char *SMTPGetFilterRejMessage(char const *pszMsgFilePath);
  169. static int SMTPLogFilter(SMTPSession & SMTPS, char const * const *ppszExec, int iExecResult,
  170.  int iExitCode, char const *pszType, char const *pszInfo);
  171. static int SMTPPreFilterExec(SMTPSession & SMTPS, FilterTokens *pToks, char **ppszPEError);
  172. static int SMTPRunFilters(SMTPSession & SMTPS, char const *pszFilterPath, char const *pszType,
  173.   char *&pszError);
  174. static int SMTPFilterMessage(SMTPSession & SMTPS, const char *pszFiltID, char *&pszError);
  175. static int SMTPHandleCmd_DATA(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  176. static int SMTPAddReceived(int iType, char const *pszAuth, char const *const *ppszMsgInfo,
  177.    char const *pszMailFrom, char const *pszRcptTo,
  178.    char const *pszMessageID, FILE * pMailFile);
  179. static char *SMTPTrimRcptLine(char *pszRcptLn);
  180. static int SMTPSubmitPackedFile(SMTPSession & SMTPS, const char *pszPkgFile);
  181. static int SMTPHandleCmd_HELO(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  182. static int SMTPHandleCmd_EHLO(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  183. static int SMTPListExtAuths(FILE * pRespFile, SMTPSession & SMTPS);
  184. static int SMTPExternalAuthSubstitute(char **ppszAuthTokens, char const *pszChallenge,
  185.       char const *pszDigest, char const *pszSecretsFile);
  186. static int SMTPCreateSecretsFile(char const *pszSecretsFile);
  187. static int SMTPExternalAuthenticate(BSOCK_HANDLE hBSock, SMTPSession & SMTPS,
  188.     char **ppszAuthTokens);
  189. static int SMTPDoAuthExternal(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszAuthType);
  190. static int SMTPDoAuthPlain(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszAuthParam);
  191. static int SMTPDoAuthLogin(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszAuthParam);
  192. static char *SMTPGetAuthFilePath(char *pszFilePath, int iMaxPath);
  193. static char *SMTPGetExtAuthFilePath(char *pszFilePath, int iMaxPath);
  194. static int SMTPTryApplyLocalAuth(SMTPSession & SMTPS, char const *pszUsername,
  195.  char const *pszPassword);
  196. static int SMTPGetUserSmtpPerms(UserInfo * pUI, SVRCFG_HANDLE hSvrConfig, char *pszPerms,
  197. int iMaxPerms);
  198. static int SMTPTryApplyLocalCMD5Auth(SMTPSession & SMTPS, char const *pszChallenge,
  199.      char const *pszUsername, char const *pszDigest);
  200. static int SMTPTryApplyUsrPwdAuth(SMTPSession & SMTPS, char const *pszUsername,
  201.   char const *pszPassword);
  202. static int SMTPTryApplyCMD5Auth(SMTPSession & SMTPS, char const *pszChallenge,
  203. char const *pszUsername, char const *pszDigest);
  204. static int SMTPDoAuthCramMD5(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszAuthParam);
  205. static int SMTPHandleCmd_AUTH(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  206. static int SMTPSendMultilineResponse(BSOCK_HANDLE hBSock, int iTimeout, FILE * pRespFile);
  207. static int SMTPHandleCmd_RSET(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  208. static int SMTPHandleCmd_NOOP(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  209. static int SMTPHandleCmd_HELP(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  210. static int SMTPHandleCmd_QUIT(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  211. static int SMTPHandleCmd_VRFY(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  212. static int SMTPHandleCmd_ETRN(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS);
  213. static SMTPConfig *SMTPGetConfigCopy(SHB_HANDLE hShbSMTP)
  214. {
  215. SMTPConfig *pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP);
  216. if (pSMTPCfg == NULL)
  217. return (NULL);
  218. SMTPConfig *pSMTPCfgCopy = (SMTPConfig *) SysAlloc(sizeof(SMTPConfig));
  219. if (pSMTPCfgCopy != NULL)
  220. memcpy(pSMTPCfgCopy, pSMTPCfg, sizeof(SMTPConfig));
  221. ShbUnlock(hShbSMTP);
  222. return (pSMTPCfgCopy);
  223. }
  224. static int SMTPLogEnabled(SHB_HANDLE hShbSMTP, SMTPConfig * pSMTPCfg)
  225. {
  226. int iDoUnlock = 0;
  227. if (pSMTPCfg == NULL) {
  228. if ((pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP)) == NULL)
  229. return (ErrGetErrorCode());
  230. ++iDoUnlock;
  231. }
  232. unsigned long ulFlags = pSMTPCfg->ulFlags;
  233. if (iDoUnlock)
  234. ShbUnlock(hShbSMTP);
  235. return ((ulFlags & SMTPF_LOG_ENABLED) ? 1 : 0);
  236. }
  237. static int SMTPCheckPeerIP(SYS_SOCKET SockFD)
  238. {
  239. char szIPMapFile[SYS_MAX_PATH] = "";
  240. CfgGetRootPath(szIPMapFile, sizeof(szIPMapFile));
  241. StrNCat(szIPMapFile, SMTP_IPMAP_FILE, sizeof(szIPMapFile));
  242. if (SysExistFile(szIPMapFile)) {
  243. SYS_INET_ADDR PeerInfo;
  244. if (SysGetPeerInfo(SockFD, PeerInfo) < 0)
  245. return (ErrGetErrorCode());
  246. if (MscCheckAllowedIP(szIPMapFile, PeerInfo, true) < 0)
  247. return (ErrGetErrorCode());
  248. }
  249. return (0);
  250. }
  251. static int SMTPThreadCountAdd(long lCount, SHB_HANDLE hShbSMTP, SMTPConfig * pSMTPCfg)
  252. {
  253. int iDoUnlock = 0;
  254. if (pSMTPCfg == NULL) {
  255. if ((pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP)) == NULL)
  256. return (ErrGetErrorCode());
  257. ++iDoUnlock;
  258. }
  259. if ((pSMTPCfg->lThreadCount + lCount) > pSMTPCfg->lMaxThreads) {
  260. if (iDoUnlock)
  261. ShbUnlock(hShbSMTP);
  262. ErrSetErrorCode(ERR_SERVER_BUSY);
  263. return (ERR_SERVER_BUSY);
  264. }
  265. pSMTPCfg->lThreadCount += lCount;
  266. if (iDoUnlock)
  267. ShbUnlock(hShbSMTP);
  268. return (0);
  269. }
  270. static unsigned int SMTPClientThread(void *pThreadData)
  271. {
  272. SYS_SOCKET SockFD = (SYS_SOCKET) (unsigned long) pThreadData;
  273. ///////////////////////////////////////////////////////////////////////////////
  274. //  Link socket to the bufferer
  275. ///////////////////////////////////////////////////////////////////////////////
  276. BSOCK_HANDLE hBSock = BSckAttach(SockFD);
  277. if (hBSock == INVALID_BSOCK_HANDLE) {
  278. ErrorPush();
  279. SysCloseSocket(SockFD);
  280. return (ErrorPop());
  281. }
  282. ///////////////////////////////////////////////////////////////////////////////
  283. //  Check IP permission
  284. ///////////////////////////////////////////////////////////////////////////////
  285. if (SMTPCheckPeerIP(SockFD) < 0) {
  286. ErrorPush();
  287. BSckVSendString(hBSock, STD_SMTP_TIMEOUT, "421 %s - %s",
  288. SMTP_SERVER_NAME, ErrGetErrorString(ErrorFetch()));
  289. BSckDetach(hBSock, 1);
  290. return (ErrorPop());
  291. }
  292. ///////////////////////////////////////////////////////////////////////////////
  293. //  Increase threads count
  294. ///////////////////////////////////////////////////////////////////////////////
  295. if (SMTPThreadCountAdd(+1, hShbSMTP) < 0) {
  296. ErrorPush();
  297. BSckVSendString(hBSock, STD_SMTP_TIMEOUT, "421 %s - %s",
  298. SMTP_SERVER_NAME, ErrGetErrorString(ErrorFetch()));
  299. BSckDetach(hBSock, 1);
  300. return (ErrorPop());
  301. }
  302. ///////////////////////////////////////////////////////////////////////////////
  303. //  Handle client session
  304. ///////////////////////////////////////////////////////////////////////////////
  305. SMTPHandleSession(hShbSMTP, hBSock);
  306. ///////////////////////////////////////////////////////////////////////////////
  307. //  Decrease threads count
  308. ///////////////////////////////////////////////////////////////////////////////
  309. SMTPThreadCountAdd(-1, hShbSMTP);
  310. ///////////////////////////////////////////////////////////////////////////////
  311. //  Unlink socket from the bufferer and close it
  312. ///////////////////////////////////////////////////////////////////////////////
  313. BSckDetach(hBSock, 1);
  314. return (0);
  315. }
  316. unsigned int SMTPThreadProc(void *pThreadData)
  317. {
  318. SMTPConfig *pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP);
  319. if (pSMTPCfg == NULL) {
  320. ErrorPush();
  321. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  322. return (ErrorPop());
  323. }
  324. int iNumSockFDs = 0;
  325. SYS_SOCKET SockFDs[MAX_SMTP_ACCEPT_ADDRESSES];
  326. if (MscCreateServerSockets(pSMTPCfg->iNumAddr, pSMTPCfg->SvrAddr, pSMTPCfg->iPort,
  327.    SMTP_LISTEN_SIZE, SockFDs, iNumSockFDs) < 0) {
  328. ErrorPush();
  329. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  330. ShbUnlock(hShbSMTP);
  331. return (ErrorPop());
  332. }
  333. ShbUnlock(hShbSMTP);
  334. SysLogMessage(LOG_LEV_MESSAGE, "%s startedn", SMTP_SERVER_NAME);
  335. for (;;) {
  336. int iNumConnSockFD = 0;
  337. SYS_SOCKET ConnSockFD[MAX_SMTP_ACCEPT_ADDRESSES];
  338. if (MscAcceptServerConnection(SockFDs, iNumSockFDs, ConnSockFD,
  339.       iNumConnSockFD, SMTPSRV_ACCEPT_TIMEOUT) < 0) {
  340. unsigned long ulFlags = SMTPF_STOP_SERVER;
  341. pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP);
  342. if (pSMTPCfg != NULL)
  343. ulFlags = pSMTPCfg->ulFlags;
  344. ShbUnlock(hShbSMTP);
  345. if (ulFlags & SMTPF_STOP_SERVER)
  346. break;
  347. else
  348. continue;
  349. }
  350. for (int ss = 0; ss < iNumConnSockFD; ss++) {
  351. SYS_THREAD hClientThread =
  352.     SysCreateServiceThread(SMTPClientThread, ConnSockFD[ss]);
  353. if (hClientThread != SYS_INVALID_THREAD)
  354. SysCloseThread(hClientThread, 0);
  355. else
  356. SysCloseSocket(ConnSockFD[ss]);
  357. }
  358. }
  359. for (int ss = 0; ss < iNumSockFDs; ss++)
  360. SysCloseSocket(SockFDs[ss]);
  361. ///////////////////////////////////////////////////////////////////////////////
  362. //  Wait for client completion
  363. ///////////////////////////////////////////////////////////////////////////////
  364. for (int iTotalWait = 0; (iTotalWait < MAX_CLIENTS_WAIT); iTotalWait += SMTP_WAIT_SLEEP) {
  365. pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP);
  366. if (pSMTPCfg == NULL)
  367. break;
  368. long lThreadCount = pSMTPCfg->lThreadCount;
  369. ShbUnlock(hShbSMTP);
  370. if (lThreadCount == 0)
  371. break;
  372. SysSleep(SMTP_WAIT_SLEEP);
  373. }
  374. SysLogMessage(LOG_LEV_MESSAGE, "%s stoppedn", SMTP_SERVER_NAME);
  375. return (0);
  376. }
  377. static int SMTPCheckSysResources(SVRCFG_HANDLE hSvrConfig)
  378. {
  379. ///////////////////////////////////////////////////////////////////////////////
  380. //  Check disk space
  381. ///////////////////////////////////////////////////////////////////////////////
  382. int iMinValue = SvrGetConfigInt("SmtpMinDiskSpace", -1, hSvrConfig);
  383. if ((iMinValue > 0) && (SvrCheckDiskSpace(1024 * (unsigned long) iMinValue) < 0))
  384. return (ErrGetErrorCode());
  385. ///////////////////////////////////////////////////////////////////////////////
  386. //  Check virtual memory
  387. ///////////////////////////////////////////////////////////////////////////////
  388. if (((iMinValue = SvrGetConfigInt("SmtpMinVirtMemSpace", -1, hSvrConfig)) > 0) &&
  389.     (SvrCheckVirtMemSpace(1024 * (unsigned long) iMinValue) < 0))
  390. return (ErrGetErrorCode());
  391. return (0);
  392. }
  393. static int SMTPCheckMapsList(SYS_INET_ADDR const &PeerInfo, char const *pszMapList,
  394.      char *pszMapName, int iMaxMapName, int &iMapCode)
  395. {
  396. for (;;) {
  397. char const *pszColon = strchr(pszMapList, ':');
  398. if (pszColon == NULL)
  399. break;
  400. int iRetCode = atoi(pszColon + 1);
  401. int iMapLength = Min((int) (pszColon - pszMapList), MAX_HOST_NAME - 1);
  402. char szMapName[MAX_HOST_NAME] = "";
  403. strncpy(szMapName, pszMapList, iMapLength);
  404. szMapName[iMapLength] = '';
  405. if (USmtpDnsMapsContained(PeerInfo, szMapName)) {
  406. if (pszMapName != NULL)
  407. StrNCpy(pszMapName, szMapName, iMaxMapName);
  408. iMapCode = iRetCode;
  409. char szIP[128] = "???.???.???.???";
  410. char szMapSpec[MAX_HOST_NAME + 128] = "";
  411. SysInetNToA(PeerInfo, szIP);
  412. SysSNPrintf(szMapSpec, sizeof(szMapSpec) - 1, "%s:%s", szMapName, szIP);
  413. ErrSetErrorCode(ERR_MAPS_CONTAINED, szMapSpec);
  414. return (ERR_MAPS_CONTAINED);
  415. }
  416. if ((pszMapList = strchr(pszColon, ',')) == NULL)
  417. break;
  418. ++pszMapList;
  419. }
  420. return (0);
  421. }
  422. static int SMTPApplyIPProps(SMTPSession & SMTPS)
  423. {
  424. char szIPPropFile[SYS_MAX_PATH] = "";
  425. CfgGetRootPath(szIPPropFile, sizeof(szIPPropFile));
  426. StrNCat(szIPPropFile, SMTP_IPPROP_FILE, sizeof(szIPPropFile));
  427. int ii;
  428. char **ppszProps;
  429. if ((ppszProps = MscGetIPProperties(szIPPropFile, SMTPS.PeerInfo)) == NULL)
  430. return (0);
  431. for (ii = 1; ppszProps[ii] != NULL; ii++) {
  432. int iNameLen;
  433. char *pszName = ppszProps[ii];
  434. char *pszVal = strchr(pszName, '=');
  435. if (pszVal == NULL)
  436. continue;
  437. iNameLen = pszVal - pszName;
  438. pszVal++;
  439. if (strncmp(pszName, "WhiteList", CStringSize("WhiteList")) == 0) {
  440. if (atoi(pszVal))
  441. SMTPS.ulFlags |= SMTPF_WHITE_LISTED;
  442. }
  443. }
  444. StrFreeStrings(ppszProps);
  445. return (0);
  446. }
  447. static int SMTPDoIPBasedInit(SMTPSession & SMTPS, char *&pszSMTPError)
  448. {
  449. ///////////////////////////////////////////////////////////////////////////////
  450. //  Check if SMTP client is in "spammers.tab" file
  451. ///////////////////////////////////////////////////////////////////////////////
  452. char *pszChkInfo = NULL;
  453. if (USmtpSpammerCheck(SMTPS.PeerInfo, pszChkInfo) < 0) {
  454. int iMapCode = 1, iErrorCode = ErrGetErrorCode();
  455. if (pszChkInfo != NULL) {
  456. char szMapCode[32] = "";
  457. if (StrParamGet(pszChkInfo, "code", szMapCode, sizeof(szMapCode) - 1))
  458. iMapCode = atoi(szMapCode);
  459. SysFree(pszChkInfo);
  460. }
  461. if (iMapCode > 0) {
  462. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  463. SMTPLogSession(SMTPS, "", "", "SNDRIP=EIPSPAM", 0);
  464. pszSMTPError = SvrGetConfigVar(SMTPS.hSvrConfig, "SmtpMsgIPBanSpammers");
  465. ErrSetErrorCode(iErrorCode);
  466. return (iErrorCode);
  467. } else if (iMapCode == 0)
  468. SMTPS.ulFlags |= SMTPF_BLOCKED_IP;
  469. else
  470. SMTPS.iCmdDelay = Max(SMTPS.iCmdDelay, Abs(iMapCode));
  471. }
  472. ///////////////////////////////////////////////////////////////////////////////
  473. //  Custom maps checking
  474. ///////////////////////////////////////////////////////////////////////////////
  475. char *pszMapsList = SvrGetConfigVar(SMTPS.hSvrConfig, "CustMapsList");
  476. if (pszMapsList != NULL) {
  477. int iMapCode = 0;
  478. char *pszCfgError = NULL;
  479. if (SMTPCheckMapsList(SMTPS.PeerInfo, pszMapsList, SMTPS.szRejMapName,
  480.       sizeof(SMTPS.szRejMapName) - 1, iMapCode) < 0) {
  481. if (iMapCode == 1) {
  482. ErrorPush();
  483. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg)) {
  484. char *pszError =
  485. StrSprint("SNDRIP=EIPMAP (%s)", SMTPS.szRejMapName);
  486. SMTPLogSession(SMTPS, "", "",
  487.        (pszError !=
  488. NULL) ? pszError : "SNDRIP=EIPMAP", 0);
  489. if (pszError != NULL)
  490. SysFree(pszError);
  491. }
  492. if ((pszCfgError =
  493.      SvrGetConfigVar(SMTPS.hSvrConfig,
  494.      "SmtpMsgIPBanMaps")) != NULL) {
  495. pszSMTPError =
  496. StrSprint("%s (%s)", pszCfgError, SMTPS.szRejMapName);
  497. SysFree(pszCfgError);
  498. } else
  499. pszSMTPError =
  500. StrSprint
  501. ("550 Denied due inclusion of your IP inside (%s)",
  502.  SMTPS.szRejMapName);
  503. SysFree(pszMapsList);
  504. return (ErrorPop());
  505. }
  506. if (iMapCode == 0)
  507. SMTPS.ulFlags |= SMTPF_MAPPED_IP;
  508. else
  509. SMTPS.iCmdDelay = Max(SMTPS.iCmdDelay, Abs(iMapCode));
  510. }
  511. SysFree(pszMapsList);
  512. }
  513. ///////////////////////////////////////////////////////////////////////////////
  514. //  RDNS client check
  515. ///////////////////////////////////////////////////////////////////////////////
  516. int iCheckValue = SvrGetConfigInt("SMTP-RDNSCheck", 0, SMTPS.hSvrConfig);
  517. if ((iCheckValue != 0) && (SysGetHostByAddr(SMTPS.PeerInfo, SMTPS.szClientFQDN) < 0)) {
  518. if (iCheckValue > 0)
  519. SMTPS.ulFlags |= SMTPF_NORDNS_IP;
  520. else
  521. SMTPS.iCmdDelay = Max(SMTPS.iCmdDelay, -iCheckValue);
  522. }
  523. return (0);
  524. }
  525. static int SMTPInitSession(SHB_HANDLE hShbSMTP, BSOCK_HANDLE hBSock,
  526.    SMTPSession & SMTPS, char *&pszSMTPError)
  527. {
  528. ZeroData(SMTPS);
  529. SMTPS.iSMTPState = stateInit;
  530. SMTPS.hShbSMTP = hShbSMTP;
  531. SMTPS.hSvrConfig = INVALID_SVRCFG_HANDLE;
  532. SMTPS.pSMTPCfg = NULL;
  533. SMTPS.pMsgFile = NULL;
  534. SMTPS.pszFrom = NULL;
  535. SMTPS.pszRcpt = NULL;
  536. SMTPS.pszSendRcpt = NULL;
  537. SMTPS.iRcptCount = 0;
  538. SMTPS.iErrorsCount = 0;
  539. SMTPS.iErrorsMax = 0;
  540. SMTPS.iCmdDelay = 0;
  541. SMTPS.ulMaxMsgSize = 0;
  542. SetEmptyString(SMTPS.szMessageID);
  543. SetEmptyString(SMTPS.szDestDomain);
  544. SetEmptyString(SMTPS.szClientFQDN);
  545. SetEmptyString(SMTPS.szClientDomain);
  546. SetEmptyString(SMTPS.szLogonUser);
  547. SetEmptyString(SMTPS.szRejMapName);
  548. SMTPS.ulFlags = 0;
  549. SMTPS.ulSetupFlags = 0;
  550. SMTPS.pszCustMsg = NULL;
  551. SysGetTmpFile(SMTPS.szMsgFile);
  552. if ((SMTPS.hSvrConfig = SvrGetConfigHandle()) == INVALID_SVRCFG_HANDLE)
  553. return (ErrGetErrorCode());
  554. if ((SMTPCheckSysResources(SMTPS.hSvrConfig) < 0) ||
  555.     (SysGetPeerInfo(BSckGetAttachedSocket(hBSock), SMTPS.PeerInfo) < 0) ||
  556.     (SysGetSockInfo(BSckGetAttachedSocket(hBSock), SMTPS.SockInfo) < 0) ||
  557.     (SMTPApplyIPProps(SMTPS) < 0)) {
  558. ErrorPush();
  559. SvrReleaseConfigHandle(SMTPS.hSvrConfig);
  560. return (ErrorPop());
  561. }
  562. ///////////////////////////////////////////////////////////////////////////////
  563. //  If the remote IP is not white-listed, do all IP based checks
  564. ///////////////////////////////////////////////////////////////////////////////
  565. if (((SMTPS.ulFlags & SMTPF_WHITE_LISTED) == 0) &&
  566.     (SMTPDoIPBasedInit(SMTPS, pszSMTPError) < 0)) {
  567. ErrorPush();
  568. SvrReleaseConfigHandle(SMTPS.hSvrConfig);
  569. return (ErrorPop());
  570. }
  571. ///////////////////////////////////////////////////////////////////////////////
  572. //  Get maximum errors count allowed in an SMTP session
  573. ///////////////////////////////////////////////////////////////////////////////
  574. SMTPS.iErrorsMax = SvrGetConfigInt("SMTP-MaxErrors", 0, SMTPS.hSvrConfig);
  575. ///////////////////////////////////////////////////////////////////////////////
  576. //  Setup SMTP domain
  577. ///////////////////////////////////////////////////////////////////////////////
  578. char *pszSvrDomain = SvrGetConfigVar(SMTPS.hSvrConfig, "SmtpServerDomain");
  579. char szIP[128] = "???.???.???.???";
  580. if (pszSvrDomain != NULL) {
  581. StrSNCpy(SMTPS.szSvrDomain, pszSvrDomain);
  582. StrSNCpy(SMTPS.szSvrFQDN, pszSvrDomain);
  583. SysFree(pszSvrDomain);
  584. } else {
  585. if (MscGetSockHost(BSckGetAttachedSocket(hBSock), SMTPS.szSvrFQDN) < 0)
  586. StrSNCpy(SMTPS.szSvrFQDN, SysInetNToA(SMTPS.SockInfo, szIP));
  587. else {
  588. ///////////////////////////////////////////////////////////////////////////////
  589. //  Try to get a valid domain from the FQDN
  590. ///////////////////////////////////////////////////////////////////////////////
  591. if (MDomGetClientDomain(SMTPS.szSvrFQDN, SMTPS.szSvrDomain,
  592. sizeof(SMTPS.szSvrDomain) - 1) < 0)
  593. StrSNCpy(SMTPS.szSvrDomain, SMTPS.szSvrFQDN);
  594. }
  595. ///////////////////////////////////////////////////////////////////////////////
  596. //  Last attempt, try fetch the "RootDomain" variable ...
  597. ///////////////////////////////////////////////////////////////////////////////
  598. if (IsEmptyString(SMTPS.szSvrDomain)) {
  599. if ((pszSvrDomain =
  600.      SvrGetConfigVar(SMTPS.hSvrConfig, "RootDomain")) == NULL) {
  601. SvrReleaseConfigHandle(SMTPS.hSvrConfig);
  602. ErrSetErrorCode(ERR_NO_DOMAIN);
  603. return (ERR_NO_DOMAIN);
  604. }
  605. StrSNCpy(SMTPS.szSvrDomain, pszSvrDomain);
  606. SysFree(pszSvrDomain);
  607. }
  608. }
  609. ///////////////////////////////////////////////////////////////////////////////
  610. //  Create timestamp
  611. ///////////////////////////////////////////////////////////////////////////////
  612. sprintf(SMTPS.szTimeStamp, "<%lu.%lu@%s>",
  613. (unsigned long) time(NULL), SysGetCurrentThreadId(), SMTPS.szSvrDomain);
  614. if ((SMTPS.pSMTPCfg = SMTPGetConfigCopy(hShbSMTP)) == NULL) {
  615. ErrorPush();
  616. SvrReleaseConfigHandle(SMTPS.hSvrConfig);
  617. return (ErrorPop());
  618. }
  619. ///////////////////////////////////////////////////////////////////////////////
  620. //  Get maximum accepted message size
  621. ///////////////////////////////////////////////////////////////////////////////
  622. SMTPS.ulMaxMsgSize = 1024 * (unsigned long) SvrGetConfigInt("MaxMessageSize",
  623.     0, SMTPS.hSvrConfig);
  624. ///////////////////////////////////////////////////////////////////////////////
  625. //  Check if the emission of "X-Auth-User:" is diabled
  626. ///////////////////////////////////////////////////////////////////////////////
  627. if (SvrGetConfigInt("DisableEmitAuthUser", 0, SMTPS.hSvrConfig))
  628. SMTPS.ulFlags |= SMTPF_NOEMIT_AUTH;
  629. ///////////////////////////////////////////////////////////////////////////////
  630. //  Try to load specific configuration
  631. ///////////////////////////////////////////////////////////////////////////////
  632. char szConfigName[128] = "";
  633. sprintf(szConfigName, "SmtpConfig-%s", SysInetNToA(SMTPS.SockInfo, szIP));
  634. char *pszSvrConfig = SvrGetConfigVar(SMTPS.hSvrConfig, szConfigName);
  635. if ((pszSvrConfig != NULL) ||
  636.     ((pszSvrConfig = SvrGetConfigVar(SMTPS.hSvrConfig, "SmtpConfig")) != NULL)) {
  637. SMTPLoadConfig(SMTPS, pszSvrConfig);
  638. SysFree(pszSvrConfig);
  639. }
  640. SMTPS.ulFlags |= SMTPS.ulSetupFlags;
  641. ///////////////////////////////////////////////////////////////////////////////
  642. //  Get custom message to append to the SMTP response
  643. ///////////////////////////////////////////////////////////////////////////////
  644. SMTPS.pszCustMsg = SvrGetConfigVar(SMTPS.hSvrConfig, "CustomSMTPMessage");
  645. return (0);
  646. }
  647. static int SMTPLoadConfig(SMTPSession & SMTPS, char const *pszSvrConfig)
  648. {
  649. char **ppszCfgTokens = StrTokenize(pszSvrConfig, ",");
  650. if (ppszCfgTokens == NULL)
  651. return (ErrGetErrorCode());
  652. for (int ii = 0; ppszCfgTokens[ii] != NULL; ii++) {
  653. if (stricmp(ppszCfgTokens[ii], "mail-auth") == 0)
  654. SMTPS.ulSetupFlags |= SMTPF_MAIL_LOCKED;
  655. }
  656. StrFreeStrings(ppszCfgTokens);
  657. return (0);
  658. }
  659. static int SMTPApplyPerms(SMTPSession & SMTPS, char const *pszPerms)
  660. {
  661. for (int ii = 0; pszPerms[ii] != ''; ii++) {
  662. switch (pszPerms[ii]) {
  663. case ('M'):
  664. SMTPS.ulFlags |= SMTPF_MAIL_UNLOCKED;
  665. break;
  666. case ('R'):
  667. SMTPS.ulFlags |= SMTPF_RELAY_ENABLED;
  668. break;
  669. case ('V'):
  670. SMTPS.ulFlags |= SMTPF_VRFY_ENABLED;
  671. break;
  672. case ('T'):
  673. SMTPS.ulFlags |= SMTPF_ETRN_ENABLED;
  674. break;
  675. case ('Z'):
  676. SMTPS.ulMaxMsgSize = 0;
  677. break;
  678. }
  679. }
  680. ///////////////////////////////////////////////////////////////////////////////
  681. //  Clear bad ip mask and command delay
  682. ///////////////////////////////////////////////////////////////////////////////
  683. SMTPS.ulFlags &= ~(SMTPF_MAPPED_IP | SMTPF_NORDNS_IP | SMTPF_BLOCKED_IP);
  684. SMTPS.iCmdDelay = 0;
  685. return (0);
  686. }
  687. static int SMTPApplyUserConfig(SMTPSession & SMTPS, UserInfo * pUI)
  688. {
  689. ///////////////////////////////////////////////////////////////////////////////
  690. //  Retrieve and apply permissions
  691. ///////////////////////////////////////////////////////////////////////////////
  692. char *pszValue = NULL;
  693. char szPerms[128] = "";
  694. if (SMTPGetUserSmtpPerms(pUI, SMTPS.hSvrConfig, szPerms, sizeof(szPerms) - 1) < 0)
  695. return (ErrGetErrorCode());
  696. SMTPApplyPerms(SMTPS, szPerms);
  697. ///////////////////////////////////////////////////////////////////////////////
  698. //  Check "MaxMessageSize" override
  699. ///////////////////////////////////////////////////////////////////////////////
  700. if ((pszValue = UsrGetUserInfoVar(pUI, "MaxMessageSize")) != NULL) {
  701. SMTPS.ulMaxMsgSize = 1024 * (unsigned long) atol(pszValue);
  702. SysFree(pszValue);
  703. }
  704. ///////////////////////////////////////////////////////////////////////////////
  705. //  Check if the emission of "X-Auth-User:" is diabled
  706. ///////////////////////////////////////////////////////////////////////////////
  707. if ((pszValue = UsrGetUserInfoVar(pUI, "DisableEmitAuthUser")) != NULL) {
  708. if (atoi(pszValue))
  709. SMTPS.ulFlags |= SMTPF_NOEMIT_AUTH;
  710. else
  711. SMTPS.ulFlags &= ~SMTPF_NOEMIT_AUTH;
  712. SysFree(pszValue);
  713. }
  714. return (0);
  715. }
  716. static int SMTPLogSession(SMTPSession & SMTPS, char const *pszSender,
  717.   char const *pszRecipient, char const *pszStatus,
  718.   unsigned long ulMsgSize)
  719. {
  720. char szTime[256] = "";
  721. MscGetTimeNbrString(szTime, sizeof(szTime) - 1);
  722. RLCK_HANDLE hResLock = RLckLockEX(SVR_LOGS_DIR SYS_SLASH_STR SMTP_LOG_FILE);
  723. if (hResLock == INVALID_RLCK_HANDLE)
  724. return (ErrGetErrorCode());
  725. char szIP[128] = "???.???.???.???";
  726. MscFileLog(SMTP_LOG_FILE, ""%s""
  727.    "t"%s""
  728.    "t"%s""
  729.    "t"%s""
  730.    "t"%s""
  731.    "t"%s""
  732.    "t"%s""
  733.    "t"%s""
  734.    "t"%s""
  735.    "t"%s""
  736.    "t"%s""
  737.    "t"%lu""
  738.    "t"%s""
  739.    "n", SMTPS.szSvrFQDN, SMTPS.szSvrDomain, SysInetNToA(SMTPS.PeerInfo, szIP),
  740.    szTime, SMTPS.szClientDomain, SMTPS.szDestDomain, pszSender, pszRecipient,
  741.    SMTPS.szMessageID, pszStatus, SMTPS.szLogonUser, ulMsgSize,
  742.    SMTPS.szClientFQDN);
  743. RLckUnlockEX(hResLock);
  744. return (0);
  745. }
  746. static int SMTPSendError(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszFormat, ...)
  747. {
  748. char *pszBuffer = NULL;
  749. STRSPRINTF(pszBuffer, pszFormat, pszFormat);
  750. if (pszBuffer == NULL)
  751. return (ErrGetErrorCode());
  752. if (SMTPS.pszCustMsg == NULL) {
  753. if (BSckSendString(hBSock, pszBuffer, SMTPS.pSMTPCfg->iTimeout) < 0) {
  754. ErrorPush();
  755. SysFree(pszBuffer);
  756. return (ErrorPop());
  757. }
  758. } else {
  759. if (BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout,
  760.     "%s - %s", pszBuffer, SMTPS.pszCustMsg) < 0) {
  761. ErrorPush();
  762. SysFree(pszBuffer);
  763. return (ErrorPop());
  764. }
  765. }
  766. SysFree(pszBuffer);
  767. ///////////////////////////////////////////////////////////////////////////////
  768. //  Increase the number of errors we encountered in this session. If the
  769. //  maximum number of allowed errors is not zero, and the current number of
  770. //  errors exceed the maximum number, we set the state to 'exit' so that the
  771. //  SMTP connection will be dropped
  772. ///////////////////////////////////////////////////////////////////////////////
  773. SMTPS.iErrorsCount++;
  774. if ((SMTPS.iErrorsMax > 0) && (SMTPS.iErrorsCount >= SMTPS.iErrorsMax)) {
  775. char szIP[128] = "";
  776. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  777. SMTPLogSession(SMTPS, SMTPS.pszFrom != NULL ? SMTPS.pszFrom: "",
  778.        "", "SMTP=EERRS", 0);
  779. SysLogMessage(LOG_LEV_MESSAGE, "SMTP forced exit (too many errors: %d) [%s]n",
  780.       SMTPS.iErrorsCount, SysInetNToA(SMTPS.PeerInfo, szIP));
  781. SMTPS.iSMTPState = stateExit;
  782. }
  783. return (0);
  784. }
  785. static int SMTPHandleSession(SHB_HANDLE hShbSMTP, BSOCK_HANDLE hBSock)
  786. {
  787. ///////////////////////////////////////////////////////////////////////////////
  788. //  Session structure declaration and init
  789. ///////////////////////////////////////////////////////////////////////////////
  790. char *pszSMTPError = NULL;
  791. SMTPSession SMTPS;
  792. if (SMTPInitSession(hShbSMTP, hBSock, SMTPS, pszSMTPError) < 0) {
  793. ErrorPush();
  794. if (pszSMTPError != NULL) {
  795. BSckSendString(hBSock, pszSMTPError, STD_SMTP_TIMEOUT);
  796. SysFree(pszSMTPError);
  797. } else
  798. BSckVSendString(hBSock, STD_SMTP_TIMEOUT,
  799. "421 %s service not available (%d), closing transmission channel",
  800. SMTP_SERVER_NAME, ErrorFetch());
  801. return (ErrorPop());
  802. }
  803. char szIP[128] = "???.???.???.???";
  804. SysLogMessage(LOG_LEV_MESSAGE, "SMTP client connection from [%s]n",
  805.       SysInetNToA(SMTPS.PeerInfo, szIP));
  806. ///////////////////////////////////////////////////////////////////////////////
  807. //  Send welcome message
  808. ///////////////////////////////////////////////////////////////////////////////
  809. char szTime[256] = "";
  810. MscGetTimeStr(szTime, sizeof(szTime) - 1);
  811. if (BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout,
  812.     "220 %s %s service ready; %s", SMTPS.szTimeStamp,
  813.     SMTP_SERVER_NAME, szTime) < 0) {
  814. ErrorPush();
  815. SMTPClearSession(SMTPS);
  816. return (ErrorPop());
  817. }
  818. ///////////////////////////////////////////////////////////////////////////////
  819. //  Command loop
  820. ///////////////////////////////////////////////////////////////////////////////
  821. char szCommand[1024] = "";
  822. while (!SvrInShutdown() && (SMTPS.iSMTPState != stateExit) &&
  823.        (BSckGetString(hBSock, szCommand, sizeof(szCommand) - 1,
  824.       SMTPS.pSMTPCfg->iSessionTimeout) != NULL) &&
  825.        (MscCmdStringCheck(szCommand) == 0)) {
  826. ///////////////////////////////////////////////////////////////////////////////
  827. //  Retrieve a fresh new configuration copy and test shutdown flag
  828. ///////////////////////////////////////////////////////////////////////////////
  829. SysFree(SMTPS.pSMTPCfg);
  830. SMTPS.pSMTPCfg = SMTPGetConfigCopy(hShbSMTP);
  831. if ((SMTPS.pSMTPCfg == NULL) || (SMTPS.pSMTPCfg->ulFlags & SMTPF_STOP_SERVER))
  832. break;
  833. ///////////////////////////////////////////////////////////////////////////////
  834. //  Handle command
  835. ///////////////////////////////////////////////////////////////////////////////
  836. SMTPHandleCommand(szCommand, hBSock, SMTPS);
  837. }
  838. SysLogMessage(LOG_LEV_MESSAGE, "SMTP client exit [%s]n",
  839.       SysInetNToA(SMTPS.PeerInfo, szIP));
  840. SMTPClearSession(SMTPS);
  841. return (0);
  842. }
  843. static void SMTPClearSession(SMTPSession & SMTPS)
  844. {
  845. if (SMTPS.pMsgFile != NULL)
  846. fclose(SMTPS.pMsgFile), SMTPS.pMsgFile = NULL;
  847. SysRemove(SMTPS.szMsgFile);
  848. if (SMTPS.hSvrConfig != INVALID_SVRCFG_HANDLE)
  849. SvrReleaseConfigHandle(SMTPS.hSvrConfig), SMTPS.hSvrConfig =
  850.     INVALID_SVRCFG_HANDLE;
  851. if (SMTPS.pSMTPCfg != NULL)
  852. SysFree(SMTPS.pSMTPCfg), SMTPS.pSMTPCfg = NULL;
  853. if (SMTPS.pszFrom != NULL)
  854. SysFree(SMTPS.pszFrom), SMTPS.pszFrom = NULL;
  855. if (SMTPS.pszRcpt != NULL)
  856. SysFree(SMTPS.pszRcpt), SMTPS.pszRcpt = NULL;
  857. if (SMTPS.pszSendRcpt != NULL)
  858. SysFree(SMTPS.pszSendRcpt), SMTPS.pszSendRcpt = NULL;
  859. if (SMTPS.pszCustMsg != NULL)
  860. SysFree(SMTPS.pszCustMsg), SMTPS.pszCustMsg = NULL;
  861. }
  862. static void SMTPResetSession(SMTPSession & SMTPS)
  863. {
  864. SMTPS.ulFlags = SMTPS.ulSetupFlags | (SMTPS.ulFlags & SMTPF_RESET_MASK);
  865. SMTPS.ullMessageID = 0;
  866. SMTPS.iRcptCount = 0;
  867. SetEmptyString(SMTPS.szMessageID);
  868. if (SMTPS.pMsgFile != NULL)
  869. fclose(SMTPS.pMsgFile), SMTPS.pMsgFile = NULL;
  870. SysRemove(SMTPS.szMsgFile);
  871. SetEmptyString(SMTPS.szDestDomain);
  872. if (SMTPS.pszFrom != NULL)
  873. SysFree(SMTPS.pszFrom), SMTPS.pszFrom = NULL;
  874. if (SMTPS.pszRcpt != NULL)
  875. SysFree(SMTPS.pszRcpt), SMTPS.pszRcpt = NULL;
  876. if (SMTPS.pszSendRcpt != NULL)
  877. SysFree(SMTPS.pszSendRcpt), SMTPS.pszSendRcpt = NULL;
  878. SMTPS.iSMTPState = (SMTPS.ulFlags & SMTPF_AUTHENTICATED) ? stateAuthenticated :
  879.     Min(SMTPS.iSMTPState, stateHelo);
  880. }
  881. static int SMTPHandleCommand(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  882. {
  883. ///////////////////////////////////////////////////////////////////////////////
  884. //  Delay protection against massive spammers
  885. ///////////////////////////////////////////////////////////////////////////////
  886. if (SMTPS.iCmdDelay > 0)
  887. SysSleep(SMTPS.iCmdDelay);
  888. ///////////////////////////////////////////////////////////////////////////////
  889. //  Command parsing and processing
  890. ///////////////////////////////////////////////////////////////////////////////
  891. int iCmdResult = -1;
  892. if (StrINComp(pszCommand, MAIL_FROM_STR) == 0)
  893. iCmdResult = SMTPHandleCmd_MAIL(pszCommand, hBSock, SMTPS);
  894. else if (StrINComp(pszCommand, RCPT_TO_STR) == 0)
  895. iCmdResult = SMTPHandleCmd_RCPT(pszCommand, hBSock, SMTPS);
  896. else if (StrCmdMatch(pszCommand, "DATA"))
  897. iCmdResult = SMTPHandleCmd_DATA(pszCommand, hBSock, SMTPS);
  898. else if (StrCmdMatch(pszCommand, "HELO"))
  899. iCmdResult = SMTPHandleCmd_HELO(pszCommand, hBSock, SMTPS);
  900. else if (StrCmdMatch(pszCommand, "EHLO"))
  901. iCmdResult = SMTPHandleCmd_EHLO(pszCommand, hBSock, SMTPS);
  902. else if (StrCmdMatch(pszCommand, "AUTH"))
  903. iCmdResult = SMTPHandleCmd_AUTH(pszCommand, hBSock, SMTPS);
  904. else if (StrCmdMatch(pszCommand, "RSET"))
  905. iCmdResult = SMTPHandleCmd_RSET(pszCommand, hBSock, SMTPS);
  906. else if (StrCmdMatch(pszCommand, "VRFY"))
  907. iCmdResult = SMTPHandleCmd_VRFY(pszCommand, hBSock, SMTPS);
  908. else if (StrCmdMatch(pszCommand, "ETRN"))
  909. iCmdResult = SMTPHandleCmd_ETRN(pszCommand, hBSock, SMTPS);
  910. else if (StrCmdMatch(pszCommand, "NOOP"))
  911. iCmdResult = SMTPHandleCmd_NOOP(pszCommand, hBSock, SMTPS);
  912. else if (StrCmdMatch(pszCommand, "HELP"))
  913. iCmdResult = SMTPHandleCmd_HELP(pszCommand, hBSock, SMTPS);
  914. else if (StrCmdMatch(pszCommand, "QUIT"))
  915. iCmdResult = SMTPHandleCmd_QUIT(pszCommand, hBSock, SMTPS);
  916. else
  917. SMTPSendError(hBSock, SMTPS, "500 Syntax error, command unrecognized");
  918. return (iCmdResult);
  919. }
  920. static int SMTPTryPopAuthIpCheck(SMTPSession & SMTPS, char const *pszUser, char const *pszDomain)
  921. {
  922. ///////////////////////////////////////////////////////////////////////////////
  923. //  Load user info
  924. ///////////////////////////////////////////////////////////////////////////////
  925. UserInfo *pUI = UsrGetUserByNameOrAlias(pszDomain, pszUser);
  926. if (pUI == NULL)
  927. return (ErrGetErrorCode());
  928. ///////////////////////////////////////////////////////////////////////////////
  929. //  Perform IP file checking
  930. ///////////////////////////////////////////////////////////////////////////////
  931. if (UPopUserIpCheck(pUI, &SMTPS.PeerInfo, SMTPS.pSMTPCfg->uPopAuthExpireTime) < 0) {
  932. ErrorPush();
  933. UsrFreeUserInfo(pUI);
  934. return (ErrorPop());
  935. }
  936. ///////////////////////////////////////////////////////////////////////////////
  937. //  Apply user configuration
  938. ///////////////////////////////////////////////////////////////////////////////
  939. if (SMTPApplyUserConfig(SMTPS, pUI) < 0) {
  940. ErrorPush();
  941. UsrFreeUserInfo(pUI);
  942. return (ErrorPop());
  943. }
  944. ///////////////////////////////////////////////////////////////////////////////
  945. //  If the user did not authenticate, set the logon user token
  946. ///////////////////////////////////////////////////////////////////////////////
  947. if (IsEmptyString(SMTPS.szLogonUser))
  948. UsrGetAddress(pUI, SMTPS.szLogonUser);
  949. UsrFreeUserInfo(pUI);
  950. return (0);
  951. }
  952. static int SMTPCheckReturnPath(const char *pszCommand, char **ppszRetDomains,
  953.        SMTPSession & SMTPS, char *&pszSMTPError)
  954. {
  955. int iDomainCount = StrStringsCount(ppszRetDomains);
  956. if (iDomainCount == 0) {
  957. if (!SvrTestConfigFlag("AllowNullSender", true, SMTPS.hSvrConfig)) {
  958. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  959. SMTPLogSession(SMTPS, "", "", "SNDR=EEMPTY", 0);
  960. pszSMTPError = SysStrDup("501 Syntax error in return path");
  961. ErrSetErrorCode(ERR_BAD_RETURN_PATH);
  962. return (ERR_BAD_RETURN_PATH);
  963. }
  964. if (SMTPS.pszFrom != NULL)
  965. SysFree(SMTPS.pszFrom);
  966. SMTPS.pszFrom = SysStrDup("");
  967. return (0);
  968. }
  969. char szMailerUser[MAX_ADDR_NAME] = "";
  970. char szMailerDomain[MAX_ADDR_NAME] = "";
  971. if (USmtpSplitEmailAddr(ppszRetDomains[0], szMailerUser, szMailerDomain) < 0) {
  972. ErrorPush();
  973. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  974. SMTPLogSession(SMTPS, ppszRetDomains[0], "", "SNDR=ESYNTAX", 0);
  975. pszSMTPError = SysStrDup("501 Syntax error in return path");
  976. return (ErrorPop());
  977. }
  978. ///////////////////////////////////////////////////////////////////////////////
  979. //  Check mailer domain for DNS/MX entries
  980. ///////////////////////////////////////////////////////////////////////////////
  981. if (SvrTestConfigFlag("CheckMailerDomain", false, SMTPS.hSvrConfig) &&
  982.     (USmtpCheckMailDomain(SMTPS.hSvrConfig, szMailerDomain) < 0)) {
  983. ErrorPush();
  984. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  985. SMTPLogSession(SMTPS, ppszRetDomains[0], "", "SNDR=ENODNS", 0);
  986. pszSMTPError = SysStrDup("505 Your domain has not DNS/MX entries");
  987. return (ErrorPop());
  988. }
  989. ///////////////////////////////////////////////////////////////////////////////
  990. //  Check if mail come from a spammer address ( spam-address.tab )
  991. ///////////////////////////////////////////////////////////////////////////////
  992. if (USmtpSpamAddressCheck(ppszRetDomains[0]) < 0) {
  993. ErrorPush();
  994. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  995. SMTPLogSession(SMTPS, ppszRetDomains[0], "", "SNDR=ESPAM", 0);
  996. if ((pszSMTPError =
  997.      SvrGetConfigVar(SMTPS.hSvrConfig, "SmtpMsgIPBanSpamAddress")) == NULL)
  998. pszSMTPError = SysStrDup("504 You are registered as spammer");
  999. return (ErrorPop());
  1000. }
  1001. ///////////////////////////////////////////////////////////////////////////////
  1002. //  Check SMTP after POP3 authentication
  1003. ///////////////////////////////////////////////////////////////////////////////
  1004. if (SvrTestConfigFlag("EnableAuthSMTP-POP3", true, SMTPS.hSvrConfig))
  1005. SMTPTryPopAuthIpCheck(SMTPS, szMailerUser, szMailerDomain);
  1006. ///////////////////////////////////////////////////////////////////////////////
  1007. //  Check extended mail from parameters
  1008. ///////////////////////////////////////////////////////////////////////////////
  1009. if (SMTPCheckMailParams(pszCommand, ppszRetDomains, SMTPS, pszSMTPError) < 0)
  1010. return (ErrGetErrorCode());
  1011. ///////////////////////////////////////////////////////////////////////////////
  1012. //  Setup From string
  1013. ///////////////////////////////////////////////////////////////////////////////
  1014. if (SMTPS.pszFrom != NULL)
  1015. SysFree(SMTPS.pszFrom);
  1016. SMTPS.pszFrom = SysStrDup(ppszRetDomains[0]);
  1017. return (0);
  1018. }
  1019. static int SMTPAddMessageInfo(SMTPSession & SMTPS)
  1020. {
  1021. return (USmtpAddMessageInfo(SMTPS.pMsgFile, SMTPS.szClientDomain, SMTPS.PeerInfo,
  1022.     SMTPS.szSvrDomain, SMTPS.SockInfo, SMTP_SERVER_NAME));
  1023. }
  1024. static int SMTPCheckMailParams(const char *pszCommand, char **ppszRetDomains,
  1025.        SMTPSession & SMTPS, char *&pszSMTPError)
  1026. {
  1027. char const *pszParams = strrchr(pszCommand, '>');
  1028. if (pszParams == NULL)
  1029. pszParams = pszCommand;
  1030. ///////////////////////////////////////////////////////////////////////////////
  1031. //  Check the SIZE parameter
  1032. ///////////////////////////////////////////////////////////////////////////////
  1033. if (SMTPS.ulMaxMsgSize != 0) {
  1034. char const *pszSize = pszParams;
  1035. while ((pszSize = StrIStr(pszSize, " SIZE=")) != NULL) {
  1036. pszSize += CStringSize(" SIZE=");
  1037. if (isdigit(*pszSize) &&
  1038.     (SMTPS.ulMaxMsgSize < (unsigned long) atol(pszSize))) {
  1039. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1040. SMTPLogSession(SMTPS,
  1041.        (ppszRetDomains[0] !=
  1042. NULL) ? ppszRetDomains[0] : "", "",
  1043.        "SIZE=EBIG",
  1044.        (unsigned long) atol(pszSize));
  1045. pszSMTPError =
  1046.     SysStrDup("552 Message exceeds fixed maximum message size");
  1047. ErrSetErrorCode(ERR_MESSAGE_SIZE);
  1048. return (ERR_MESSAGE_SIZE);
  1049. }
  1050. }
  1051. }
  1052. return (0);
  1053. }
  1054. static int SMTPHandleCmd_MAIL(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  1055. {
  1056. if ((SMTPS.iSMTPState != stateHelo) && (SMTPS.iSMTPState != stateAuthenticated)) {
  1057. SMTPResetSession(SMTPS);
  1058. SMTPSendError(hBSock, SMTPS, "503 Bad sequence of commands");
  1059. ErrSetErrorCode(ERR_SMTP_BAD_CMD_SEQUENCE);
  1060. return (ERR_SMTP_BAD_CMD_SEQUENCE);
  1061. }
  1062. ///////////////////////////////////////////////////////////////////////////////
  1063. //  Split the RETURN PATH
  1064. ///////////////////////////////////////////////////////////////////////////////
  1065. char **ppszRetDomains = USmtpGetPathStrings(pszCommand);
  1066. if (ppszRetDomains == NULL) {
  1067. ErrorPush();
  1068. SMTPResetSession(SMTPS);
  1069. SMTPSendError(hBSock, SMTPS,
  1070.       "501 Syntax error in parameters or arguments: (%d)",
  1071.       ErrorFetch());
  1072. return (ErrorPop());
  1073. }
  1074. ///////////////////////////////////////////////////////////////////////////////
  1075. //  Check RETURN PATH
  1076. ///////////////////////////////////////////////////////////////////////////////
  1077. char *pszSMTPError = NULL;
  1078. if (SMTPCheckReturnPath(pszCommand, ppszRetDomains, SMTPS, pszSMTPError) < 0) {
  1079. ErrorPush();
  1080. StrFreeStrings(ppszRetDomains);
  1081. SMTPResetSession(SMTPS);
  1082. SMTPSendError(hBSock, SMTPS, "%s", pszSMTPError);
  1083. SysFree(pszSMTPError);
  1084. return (ErrorPop());
  1085. }
  1086. StrFreeStrings(ppszRetDomains);
  1087. ///////////////////////////////////////////////////////////////////////////////
  1088. //  If the incoming IP is "mapped" stop here
  1089. ///////////////////////////////////////////////////////////////////////////////
  1090. if (SMTPS.ulFlags & (SMTPF_MAPPED_IP | SMTPF_NORDNS_IP | SMTPF_BLOCKED_IP)) {
  1091. char *pszSMTPError = NULL;
  1092. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg)) {
  1093. if (SMTPS.ulFlags & SMTPF_MAPPED_IP) {
  1094. char *pszError =
  1095. StrSprint("SNDRIP=EIPMAP (%s)", SMTPS.szRejMapName);
  1096. SMTPLogSession(SMTPS, SMTPS.pszFrom, "",
  1097.        (pszError != NULL) ? pszError : "SNDRIP=EIPMAP",
  1098.        0);
  1099. if (pszError != NULL)
  1100. SysFree(pszError);
  1101. } else if (SMTPS.ulFlags & SMTPF_NORDNS_IP)
  1102. SMTPLogSession(SMTPS, SMTPS.pszFrom, "", "SNDRIP=ERDNS", 0);
  1103. else
  1104. SMTPLogSession(SMTPS, SMTPS.pszFrom, "", "SNDRIP=EIPSPAM", 0);
  1105. }
  1106. if (SMTPS.ulFlags & SMTPF_BLOCKED_IP)
  1107. pszSMTPError = SvrGetConfigVar(SMTPS.hSvrConfig, "SmtpMsgIPBanSpammers");
  1108. SMTPResetSession(SMTPS);
  1109. if (pszSMTPError == NULL)
  1110. SMTPSendError(hBSock, SMTPS, "551 Server access forbidden by your IP");
  1111. else {
  1112. SMTPSendError(hBSock, SMTPS, "%s", pszSMTPError);
  1113. SysFree(pszSMTPError);
  1114. }
  1115. ErrSetErrorCode(ERR_SMTP_USE_FORBIDDEN);
  1116. return (ERR_SMTP_USE_FORBIDDEN);
  1117. }
  1118. ///////////////////////////////////////////////////////////////////////////////
  1119. //  If MAIL command is locked stop here
  1120. ///////////////////////////////////////////////////////////////////////////////
  1121. if ((SMTPS.ulFlags & SMTPF_MAIL_LOCKED) && !(SMTPS.ulFlags & SMTPF_MAIL_UNLOCKED)) {
  1122. SMTPResetSession(SMTPS);
  1123. SMTPSendError(hBSock, SMTPS, "551 Server use forbidden");
  1124. ErrSetErrorCode(ERR_SMTP_USE_FORBIDDEN);
  1125. return (ERR_SMTP_USE_FORBIDDEN);
  1126. }
  1127. ///////////////////////////////////////////////////////////////////////////////
  1128. //  Prepare mail file
  1129. ///////////////////////////////////////////////////////////////////////////////
  1130. if ((SMTPS.pMsgFile = fopen(SMTPS.szMsgFile, "w+b")) == NULL) {
  1131. SMTPResetSession(SMTPS);
  1132. SMTPSendError(hBSock, SMTPS,
  1133.       "451 Requested action aborted: (%d) local error in processing",
  1134.       ERR_FILE_CREATE);
  1135. ErrSetErrorCode(ERR_FILE_CREATE, SMTPS.szMsgFile);
  1136. return (ERR_FILE_CREATE);
  1137. }
  1138. ///////////////////////////////////////////////////////////////////////////////
  1139. //  Write message infos ( 1st row of the smtp-mail file )
  1140. ///////////////////////////////////////////////////////////////////////////////
  1141. if (SMTPAddMessageInfo(SMTPS) < 0) {
  1142. ErrorPush();
  1143. SMTPResetSession(SMTPS);
  1144. SMTPSendError(hBSock, SMTPS,
  1145.       "451 Requested action aborted: (%d) local error in processing",
  1146.       ErrorFetch());
  1147. return (ErrorPop());
  1148. }
  1149. ///////////////////////////////////////////////////////////////////////////////
  1150. //  Write domain ( 2nd row of the smtp-mail file )
  1151. ///////////////////////////////////////////////////////////////////////////////
  1152. if (StrWriteCRLFString(SMTPS.pMsgFile, SMTPS.szSvrDomain) < 0) {
  1153. ErrorPush();
  1154. SMTPResetSession(SMTPS);
  1155. SMTPSendError(hBSock, SMTPS,
  1156.       "451 Requested action aborted: (%d) local error in processing",
  1157.       ErrorFetch());
  1158. return (ErrorPop());
  1159. }
  1160. ///////////////////////////////////////////////////////////////////////////////
  1161. //  Get SMTP message ID and write it to file ( 3th row of the smtp-mail file )
  1162. ///////////////////////////////////////////////////////////////////////////////
  1163. if (SvrGetMessageID(&SMTPS.ullMessageID) < 0) {
  1164. ErrorPush();
  1165. SMTPResetSession(SMTPS);
  1166. SMTPSendError(hBSock, SMTPS,
  1167.       "451 Requested action aborted: (%d) local error in processing",
  1168.       ErrorFetch());
  1169. return (ErrorPop());
  1170. }
  1171. sprintf(SMTPS.szMessageID, "S" SYS_LLX_FMT, SMTPS.ullMessageID);
  1172. if (StrWriteCRLFString(SMTPS.pMsgFile, SMTPS.szMessageID) < 0) {
  1173. ErrorPush();
  1174. SMTPResetSession(SMTPS);
  1175. SMTPSendError(hBSock, SMTPS,
  1176.       "451 Requested action aborted: (%d) local error in processing",
  1177.       ErrorFetch());
  1178. return (ErrorPop());
  1179. }
  1180. ///////////////////////////////////////////////////////////////////////////////
  1181. //  Write MAIL FROM ( 4th row of the smtp-mail file )
  1182. ///////////////////////////////////////////////////////////////////////////////
  1183. if (StrWriteCRLFString(SMTPS.pMsgFile, pszCommand) < 0) {
  1184. ErrorPush();
  1185. SMTPResetSession(SMTPS);
  1186. SMTPSendError(hBSock, SMTPS,
  1187.       "451 Requested action aborted: (%d) local error in processing",
  1188.       ErrorFetch());
  1189. return (ErrorPop());
  1190. }
  1191. BSckSendString(hBSock, "250 OK", SMTPS.pSMTPCfg->iTimeout);
  1192. SMTPS.iSMTPState = stateMail;
  1193. return (0);
  1194. }
  1195. static int SMTPCheckRelayCapability(SMTPSession & SMTPS, char const *pszDestDomain)
  1196. {
  1197. ///////////////////////////////////////////////////////////////////////////////
  1198. //  OK if enabled ( authentication )
  1199. ///////////////////////////////////////////////////////////////////////////////
  1200. if (SMTPS.ulFlags & SMTPF_RELAY_ENABLED)
  1201. return (0);
  1202. ///////////////////////////////////////////////////////////////////////////////
  1203. //  OK if destination domain is a custom-handled domain
  1204. ///////////////////////////////////////////////////////////////////////////////
  1205. if (USmlCustomizedDomain(pszDestDomain) == 0)
  1206. return (0);
  1207. ///////////////////////////////////////////////////////////////////////////////
  1208. //  IP based relay check
  1209. ///////////////////////////////////////////////////////////////////////////////
  1210. return (USmtpIsAllowedRelay(SMTPS.PeerInfo, SMTPS.hSvrConfig));
  1211. }
  1212. static int SMTPCheckForwardPath(char **ppszFwdDomains, SMTPSession & SMTPS,
  1213. char *&pszRealRcpt, char *&pszSMTPError)
  1214. {
  1215. int iDomainCount = StrStringsCount(ppszFwdDomains);
  1216. if (iDomainCount == 0) {
  1217. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1218. SMTPLogSession(SMTPS, SMTPS.pszFrom, "", "RCPT=ESYNTAX", 0);
  1219. pszSMTPError = SysStrDup("501 Syntax error in forward path");
  1220. ErrSetErrorCode(ERR_BAD_FORWARD_PATH);
  1221. return (ERR_BAD_FORWARD_PATH);
  1222. }
  1223. char szDestUser[MAX_ADDR_NAME] = "";
  1224. char szDestDomain[MAX_ADDR_NAME] = "";
  1225. char szRealUser[MAX_ADDR_NAME] = "";
  1226. if (USmtpSplitEmailAddr(ppszFwdDomains[iDomainCount - 1], szDestUser, szDestDomain) < 0) {
  1227. ErrorPush();
  1228. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1229. SMTPLogSession(SMTPS, SMTPS.pszFrom, ppszFwdDomains[0], "RCPT=ESYNTAX",
  1230.        0);
  1231. pszSMTPError = SysStrDup("501 Syntax error in forward path");
  1232. return (ErrorPop());
  1233. }
  1234. if (iDomainCount == 1) {
  1235. if (USmlIsCmdAliasAccount(szDestDomain, szDestUser) == 0) {
  1236. ///////////////////////////////////////////////////////////////////////////////
  1237. //  The recipient is handled with cmdaliases
  1238. ///////////////////////////////////////////////////////////////////////////////
  1239. } else if (MDomIsHandledDomain(szDestDomain) == 0) {
  1240. ///////////////////////////////////////////////////////////////////////////////
  1241. //  Check user existance
  1242. ///////////////////////////////////////////////////////////////////////////////
  1243. UserInfo *pUI = UsrGetUserByNameOrAlias(szDestDomain, szDestUser);
  1244. if (pUI != NULL) {
  1245. ///////////////////////////////////////////////////////////////////////////////
  1246. //  Check if the account is enabled for receiving
  1247. ///////////////////////////////////////////////////////////////////////////////
  1248. if (!UsrGetUserInfoVarInt(pUI, "ReceiveEnable", 1)) {
  1249. UsrFreeUserInfo(pUI);
  1250. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1251. SMTPLogSession(SMTPS, SMTPS.pszFrom,
  1252.        ppszFwdDomains[0], "RCPT=EDSBL",
  1253.        0);
  1254. pszSMTPError = StrSprint("550 Account disabled <%s@%s>",
  1255.  szDestUser, szDestDomain);
  1256. ErrSetErrorCode(ERR_USER_DISABLED);
  1257. return (ERR_USER_DISABLED);
  1258. }
  1259. if (UsrGetUserType(pUI) == usrTypeUser) {
  1260. ///////////////////////////////////////////////////////////////////////////////
  1261. //  Target is a normal user
  1262. ///////////////////////////////////////////////////////////////////////////////
  1263. ///////////////////////////////////////////////////////////////////////////////
  1264. //  Check user mailbox size
  1265. ///////////////////////////////////////////////////////////////////////////////
  1266. if (UPopCheckMailboxSize(pUI) < 0) {
  1267. ErrorPush();
  1268. UsrFreeUserInfo(pUI);
  1269. if (SMTPLogEnabled
  1270.     (SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1271. SMTPLogSession(SMTPS, SMTPS.pszFrom,
  1272.        ppszFwdDomains[0],
  1273.        "RCPT=EFULL", 0);
  1274. pszSMTPError =
  1275. StrSprint
  1276. ("552 Requested mail action aborted: exceeded storage allocation - <%s@%s>",
  1277.  szDestUser, szDestDomain);
  1278. return (ErrorPop());
  1279. }
  1280. } else {
  1281. ///////////////////////////////////////////////////////////////////////////////
  1282. //  Target is a mailing list
  1283. ///////////////////////////////////////////////////////////////////////////////
  1284. ///////////////////////////////////////////////////////////////////////////////
  1285. //  Check if client can post to this mailing list
  1286. ///////////////////////////////////////////////////////////////////////////////
  1287. if (UsrMLCheckUserPost(pUI, SMTPS.pszFrom,
  1288.        IsEmptyString(SMTPS.
  1289.      szLogonUser) ? NULL :
  1290.        SMTPS.szLogonUser) < 0) {
  1291. ErrorPush();
  1292. UsrFreeUserInfo(pUI);
  1293. if (SMTPLogEnabled
  1294.     (SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1295. SMTPLogSession(SMTPS, SMTPS.pszFrom,
  1296.        ppszFwdDomains[0],
  1297.        "RCPT=EACCESS", 0);
  1298. pszSMTPError =
  1299. StrSprint
  1300. ("557 Access denied <%s@%s> for user <%s>",
  1301.  szDestUser, szDestDomain, SMTPS.pszFrom);
  1302. return (ErrorPop());
  1303. }
  1304. }
  1305. ///////////////////////////////////////////////////////////////////////////////
  1306. //  Extract the real user address
  1307. ///////////////////////////////////////////////////////////////////////////////
  1308. UsrGetAddress(pUI, szRealUser);
  1309. UsrFreeUserInfo(pUI);
  1310. } else {
  1311. ///////////////////////////////////////////////////////////////////////////////
  1312. //  Recipient domain is local but no account is found inside the standard
  1313. //  users/aliases database and the account is not handled with cmdaliases.
  1314. //  It's pretty much time to report a recipient error
  1315. ///////////////////////////////////////////////////////////////////////////////
  1316. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1317. SMTPLogSession(SMTPS, SMTPS.pszFrom, ppszFwdDomains[0],
  1318.        "RCPT=EAVAIL", 0);
  1319. pszSMTPError = StrSprint("550 Mailbox unavailable <%s@%s>",
  1320.  szDestUser, szDestDomain);
  1321. ErrSetErrorCode(ERR_USER_NOT_LOCAL);
  1322. return (ERR_USER_NOT_LOCAL);
  1323. }
  1324. } else {
  1325. ///////////////////////////////////////////////////////////////////////////////
  1326. //  Check relay permission
  1327. ///////////////////////////////////////////////////////////////////////////////
  1328. if (SMTPCheckRelayCapability(SMTPS, szDestDomain) < 0) {
  1329. ErrorPush();
  1330. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1331. SMTPLogSession(SMTPS, SMTPS.pszFrom, ppszFwdDomains[0],
  1332.        "RCPT=ERELAY", 0);
  1333. pszSMTPError = SysStrDup("550 Relay denied");
  1334. return (ErrorPop());
  1335. }
  1336. }
  1337. } else {
  1338. ///////////////////////////////////////////////////////////////////////////////
  1339. //  Check relay permission
  1340. ///////////////////////////////////////////////////////////////////////////////
  1341. if (SMTPCheckRelayCapability(SMTPS, szDestDomain) < 0) {
  1342. ErrorPush();
  1343. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1344. SMTPLogSession(SMTPS, SMTPS.pszFrom, ppszFwdDomains[0],
  1345.        "RCPT=ERELAY", 0);
  1346. pszSMTPError = SysStrDup("550 Relay denied");
  1347. return (ErrorPop());
  1348. }
  1349. }
  1350. ///////////////////////////////////////////////////////////////////////////////
  1351. //  Retrieve destination domain
  1352. ///////////////////////////////////////////////////////////////////////////////
  1353. if (USmtpSplitEmailAddr(ppszFwdDomains[0], NULL, SMTPS.szDestDomain) < 0) {
  1354. ErrorPush();
  1355. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1356. SMTPLogSession(SMTPS, SMTPS.pszFrom, ppszFwdDomains[0], "RCPT=ESYNTAX",
  1357.        0);
  1358. pszSMTPError = SysStrDup("501 Syntax error in forward path");
  1359. return (ErrorPop());
  1360. }
  1361. ///////////////////////////////////////////////////////////////////////////////
  1362. //  Setup SendRcpt string ( it'll be used to build "RCPT TO:<>" line into
  1363. //  the message file
  1364. ///////////////////////////////////////////////////////////////////////////////
  1365. if (SMTPS.pszSendRcpt != NULL)
  1366. SysFree(SMTPS.pszSendRcpt);
  1367. if ((SMTPS.pszSendRcpt = USmtpBuildRcptPath(ppszFwdDomains, SMTPS.hSvrConfig)) == NULL) {
  1368. ErrorPush();
  1369. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1370. SMTPLogSession(SMTPS, SMTPS.pszFrom, ppszFwdDomains[0], "RCPT=ESYNTAX",
  1371.        0);
  1372. pszSMTPError = SysStrDup("501 Syntax error in forward path");
  1373. return (ErrorPop());
  1374. }
  1375. ///////////////////////////////////////////////////////////////////////////////
  1376. //  Setup the Real Rcpt string
  1377. ///////////////////////////////////////////////////////////////////////////////
  1378. if (!IsEmptyString(szRealUser))
  1379. pszRealRcpt = SysStrDup(szRealUser);
  1380. ///////////////////////////////////////////////////////////////////////////////
  1381. //  Setup Rcpt string
  1382. ///////////////////////////////////////////////////////////////////////////////
  1383. if (SMTPS.pszRcpt != NULL)
  1384. SysFree(SMTPS.pszRcpt);
  1385. SMTPS.pszRcpt = SysStrDup(ppszFwdDomains[0]);
  1386. return (0);
  1387. }
  1388. static int SMTPHandleCmd_RCPT(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  1389. {
  1390. if ((SMTPS.iSMTPState != stateMail) && (SMTPS.iSMTPState != stateRcpt)) {
  1391. SMTPResetSession(SMTPS);
  1392. SMTPSendError(hBSock, SMTPS, "503 Bad sequence of commands");
  1393. ErrSetErrorCode(ERR_SMTP_BAD_CMD_SEQUENCE);
  1394. return (ERR_SMTP_BAD_CMD_SEQUENCE);
  1395. }
  1396. ///////////////////////////////////////////////////////////////////////////////
  1397. //  Check recipients count
  1398. ///////////////////////////////////////////////////////////////////////////////
  1399. if (SMTPS.iRcptCount >= SMTPS.pSMTPCfg->iMaxRcpts) {
  1400. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1401. SMTPLogSession(SMTPS, SMTPS.pszFrom, "", "RCPT=ENBR", 0);
  1402. SMTPSendError(hBSock, SMTPS, "552 Too many recipients");
  1403. ErrSetErrorCode(ERR_SMTP_TOO_MANY_RECIPIENTS);
  1404. return (ERR_SMTP_TOO_MANY_RECIPIENTS);
  1405. }
  1406. char **ppszFwdDomains = USmtpGetPathStrings(pszCommand);
  1407. if (ppszFwdDomains == NULL) {
  1408. ErrorPush();
  1409. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1410. SMTPLogSession(SMTPS, SMTPS.pszFrom, "", "RCPT=ESYNTAX", 0);
  1411. SMTPResetSession(SMTPS);
  1412. SMTPSendError(hBSock, SMTPS,
  1413.       "501 Syntax error in parameters or arguments: (%d)",
  1414.       ErrorFetch());
  1415. return (ErrorPop());
  1416. }
  1417. ///////////////////////////////////////////////////////////////////////////////
  1418. //  Check FORWARD PATH
  1419. ///////////////////////////////////////////////////////////////////////////////
  1420. char *pszRealRcpt = NULL;
  1421. char *pszSMTPError = NULL;
  1422. if (SMTPCheckForwardPath(ppszFwdDomains, SMTPS, pszRealRcpt,
  1423.  pszSMTPError) < 0) {
  1424. ErrorPush();
  1425. StrFreeStrings(ppszFwdDomains);
  1426. SMTPSendError(hBSock, SMTPS, "%s", pszSMTPError);
  1427. SysFree(pszSMTPError);
  1428. return (ErrorPop());
  1429. }
  1430. StrFreeStrings(ppszFwdDomains);
  1431. ///////////////////////////////////////////////////////////////////////////////
  1432. //  Log SMTP session
  1433. ///////////////////////////////////////////////////////////////////////////////
  1434. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1435. SMTPLogSession(SMTPS, SMTPS.pszFrom, SMTPS.pszRcpt, "RCPT=OK", 0);
  1436. ///////////////////////////////////////////////////////////////////////////////
  1437. //  Write RCPT TO ( 5th[,...] row(s) of the smtp-mail file )
  1438. ///////////////////////////////////////////////////////////////////////////////
  1439. fprintf(SMTPS.pMsgFile, "RCPT TO:<%s> {ra=%s}rn", SMTPS.pszSendRcpt,
  1440. (pszRealRcpt != NULL) ? pszRealRcpt: SMTPS.pszSendRcpt);
  1441. if (pszRealRcpt != NULL)
  1442. SysFree(pszRealRcpt);
  1443. BSckSendString(hBSock, "250 OK", SMTPS.pSMTPCfg->iTimeout);
  1444. ++SMTPS.iRcptCount;
  1445. SMTPS.iSMTPState = stateRcpt;
  1446. return (0);
  1447. }
  1448. static int SMTPGetFilterFile(const char *pszFiltID, char *pszFileName, int iMaxName)
  1449. {
  1450. char szMailRoot[SYS_MAX_PATH] = "";
  1451. CfgGetRootPath(szMailRoot, sizeof(szMailRoot));
  1452. SysSNPrintf(pszFileName, iMaxName - 1, "%sfilters.%s.tab", szMailRoot, pszFiltID);
  1453. return (SysExistFile(pszFileName));
  1454. }
  1455. static int SMTPFilterMacroSubstitutes(char **ppszCmdTokens, SMTPSession & SMTPS)
  1456. {
  1457. for (int ii = 0; ppszCmdTokens[ii] != NULL; ii++) {
  1458. if (strcmp(ppszCmdTokens[ii], "@@FILE") == 0) {
  1459. char *pszNewValue = SysStrDup(SMTPS.szMsgFile);
  1460. if (pszNewValue == NULL)
  1461. return (ErrGetErrorCode());
  1462. SysFree(ppszCmdTokens[ii]);
  1463. ppszCmdTokens[ii] = pszNewValue;
  1464. } else if (strcmp(ppszCmdTokens[ii], "@@USERAUTH") == 0) {
  1465. char *pszNewValue = SysStrDup(IsEmptyString(SMTPS.szLogonUser) ?
  1466.       "-": SMTPS.szLogonUser);
  1467. if (pszNewValue == NULL)
  1468. return (ErrGetErrorCode());
  1469. SysFree(ppszCmdTokens[ii]);
  1470. ppszCmdTokens[ii] = pszNewValue;
  1471. } else if (strcmp(ppszCmdTokens[ii], "@@REMOTEADDR") == 0) {
  1472. char szIP[128] = "???.???.???.???";
  1473. char *pszNewValue = SysStrDup(SysInetNToA(SMTPS.PeerInfo, szIP));
  1474. if (pszNewValue == NULL)
  1475. return (ErrGetErrorCode());
  1476. SysFree(ppszCmdTokens[ii]);
  1477. ppszCmdTokens[ii] = pszNewValue;
  1478. } else if (strcmp(ppszCmdTokens[ii], "@@LOCALADDR") == 0) {
  1479. char szIP[128] = "???.???.???.???";
  1480. char *pszNewValue = SysStrDup(SysInetNToA(SMTPS.SockInfo, szIP));
  1481. if (pszNewValue == NULL)
  1482. return (ErrGetErrorCode());
  1483. SysFree(ppszCmdTokens[ii]);
  1484. ppszCmdTokens[ii] = pszNewValue;
  1485. }
  1486. }
  1487. return (0);
  1488. }
  1489. static char *SMTPGetFilterRejMessage(char const *pszMsgFilePath)
  1490. {
  1491. FILE *pFile;
  1492. char szRejFilePath[SYS_MAX_PATH] = "";
  1493. char szRejMsg[512] = "";
  1494. SysSNPrintf(szRejFilePath, sizeof(szRejFilePath) - 1, "%s.rej", pszMsgFilePath);
  1495. if ((pFile = fopen(szRejFilePath, "rb")) == NULL)
  1496. return NULL;
  1497. MscFGets(szRejMsg, sizeof(szRejMsg) - 1, pFile);
  1498. fclose(pFile);
  1499. SysRemove(szRejFilePath);
  1500. return (SysStrDup(szRejMsg));
  1501. }
  1502. static int SMTPLogFilter(SMTPSession & SMTPS, char const * const *ppszExec, int iExecResult,
  1503.  int iExitCode, char const *pszType, char const *pszInfo)
  1504. {
  1505. FilterLogInfo FLI;
  1506. FLI.pszSender = SMTPS.pszFrom != NULL ? SMTPS.pszFrom: "";
  1507. FLI.pszRecipient = SMTPS.pszRcpt != NULL ? (SMTPS.iRcptCount == 1 ? SMTPS.pszRcpt: "*"): "";
  1508. FLI.LocalAddr = SMTPS.SockInfo;
  1509. FLI.RemoteAddr = SMTPS.PeerInfo;
  1510. FLI.ppszExec = ppszExec;
  1511. FLI.iExecResult = iExecResult;
  1512. FLI.iExitCode = iExitCode;
  1513. FLI.pszType = pszType;
  1514. FLI.pszInfo = pszInfo != NULL ? pszInfo: "";
  1515. return (FilLogFilter(&FLI));
  1516. }
  1517. static int SMTPPreFilterExec(SMTPSession & SMTPS, FilterTokens *pToks, char **ppszPEError)
  1518. {
  1519. FilterExecCtx FCtx;
  1520. FCtx.pToks = pToks;
  1521. FCtx.pszAuthName = SMTPS.szLogonUser;
  1522. return (FilExecPreParse(&FCtx, ppszPEError));
  1523. }
  1524. static int SMTPRunFilters(SMTPSession & SMTPS, char const *pszFilterPath, char const *pszType,
  1525.   char *&pszError)
  1526. {
  1527. ///////////////////////////////////////////////////////////////////////////////
  1528. //  Share lock the filter file
  1529. ///////////////////////////////////////////////////////////////////////////////
  1530. char szResLock[SYS_MAX_PATH] = "";
  1531. RLCK_HANDLE hResLock = RLckLockSH(CfgGetBasedPath(pszFilterPath, szResLock,
  1532.   sizeof(szResLock)));
  1533. if (hResLock == INVALID_RLCK_HANDLE)
  1534. return (ErrGetErrorCode());
  1535. ///////////////////////////////////////////////////////////////////////////////
  1536. //  This should not happen but if it happens we let the message pass through
  1537. ///////////////////////////////////////////////////////////////////////////////
  1538. FILE *pFiltFile = fopen(pszFilterPath, "rt");
  1539. if (pFiltFile == NULL) {
  1540. RLckUnlockSH(hResLock);
  1541. return (0);
  1542. }
  1543. ///////////////////////////////////////////////////////////////////////////////
  1544. //  Filter this message
  1545. ///////////////////////////////////////////////////////////////////////////////
  1546. int iFieldsCount, iExitCode, iExitFlags, iExecResult;
  1547. char szFiltLine[1024] = "";
  1548. while (MscGetConfigLine(szFiltLine, sizeof(szFiltLine) - 1, pFiltFile) != NULL) {
  1549. char **ppszCmdTokens = StrGetTabLineStrings(szFiltLine);
  1550. if (ppszCmdTokens == NULL)
  1551. continue;
  1552. if ((iFieldsCount = StrStringsCount(ppszCmdTokens)) < 1) {
  1553. StrFreeStrings(ppszCmdTokens);
  1554. continue;
  1555. }
  1556. ///////////////////////////////////////////////////////////////////////////////
  1557. //  Perform pre-exec filtering (like exec exclude if authenticated, ...)
  1558. ///////////////////////////////////////////////////////////////////////////////
  1559. char *pszPEError = NULL;
  1560. FilterTokens Toks;
  1561. Toks.ppszCmdTokens = ppszCmdTokens;
  1562. Toks.iTokenCount = iFieldsCount;
  1563. if (SMTPPreFilterExec(SMTPS, &Toks, &pszPEError) < 0) {
  1564. if (bFilterLogEnabled)
  1565. SMTPLogFilter(SMTPS, Toks.ppszCmdTokens, -1,
  1566.       -1, pszType, pszPEError);
  1567. if (pszPEError != NULL)
  1568. SysFree(pszPEError);
  1569. StrFreeStrings(ppszCmdTokens);
  1570. continue;
  1571. }
  1572. ///////////////////////////////////////////////////////////////////////////////
  1573. //  Do filter line macro substitution
  1574. ///////////////////////////////////////////////////////////////////////////////
  1575. SMTPFilterMacroSubstitutes(Toks.ppszCmdTokens, SMTPS);
  1576. iExitCode = -1;
  1577. iExitFlags = 0;
  1578. iExecResult = SysExec(Toks.ppszCmdTokens[0], &Toks.ppszCmdTokens[0],
  1579.       iFilterTimeout, SYS_PRIORITY_NORMAL, &iExitCode);
  1580. ///////////////////////////////////////////////////////////////////////////////
  1581. //  Log filter execution, if enabled
  1582. ///////////////////////////////////////////////////////////////////////////////
  1583. if (bFilterLogEnabled)
  1584. SMTPLogFilter(SMTPS, Toks.ppszCmdTokens, iExecResult,
  1585.       iExitCode, pszType, NULL);
  1586. if (iExecResult == 0) {
  1587. SysLogMessage(LOG_LEV_MESSAGE,
  1588.       "SMTP filter run: Filter = "%s" Retcode = %dn",
  1589.       Toks.ppszCmdTokens[0], iExitCode);
  1590. iExitFlags = iExitCode & SMTP_FILTER_FL_MASK;
  1591. iExitCode &= ~SMTP_FILTER_FL_MASK;
  1592. if (iExitCode == SMTP_FILTER_REJECT_CODE) {
  1593. StrFreeStrings(ppszCmdTokens);
  1594. fclose(pFiltFile);
  1595. RLckUnlockSH(hResLock);
  1596. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1597. SMTPLogSession(SMTPS, SMTPS.pszFrom, SMTPS.pszRcpt,
  1598.        "DATA=EFILTER", 0);
  1599. pszError = SMTPGetFilterRejMessage(SMTPS.szMsgFile);
  1600. ErrSetErrorCode(ERR_FILTERED_MESSAGE);
  1601. return (ERR_FILTERED_MESSAGE);
  1602. }
  1603. } else {
  1604. SysLogMessage(LOG_LEV_ERROR,
  1605.       "SMTP filter error (%d): Filter = "%s"n",
  1606.       iExecResult, Toks.ppszCmdTokens[0]);
  1607. }
  1608. StrFreeStrings(ppszCmdTokens);
  1609. if (iExitFlags & SMTP_FILTER_FL_BREAK)
  1610. break;
  1611. }
  1612. fclose(pFiltFile);
  1613. RLckUnlockSH(hResLock);
  1614. return (0);
  1615. }
  1616. static int SMTPFilterMessage(SMTPSession & SMTPS, const char *pszFiltID, char *&pszError)
  1617. {
  1618. int iReOpen = 0;
  1619. char szFilterFile[SYS_MAX_PATH] = "";
  1620. if (!SMTPGetFilterFile(pszFiltID, szFilterFile, sizeof(szFilterFile) - 1))
  1621. return (0);
  1622. if (SMTPS.pMsgFile != NULL) {
  1623. if (fflush(SMTPS.pMsgFile)) {
  1624. ErrSetErrorCode(ERR_FILE_WRITE, SMTPS.szMsgFile);
  1625. return (ERR_FILE_WRITE);
  1626. }
  1627. if (fclose(SMTPS.pMsgFile)) {
  1628. SMTPS.pMsgFile = NULL;
  1629. ErrSetErrorCode(ERR_FILE_WRITE, SMTPS.szMsgFile);
  1630. return (ERR_FILE_WRITE);
  1631. }
  1632. SMTPS.pMsgFile = NULL;
  1633. iReOpen++;
  1634. }
  1635. if (SMTPRunFilters(SMTPS, szFilterFile, pszFiltID, pszError) < 0)
  1636. return (ErrGetErrorCode());
  1637. if (iReOpen) {
  1638. if ((SMTPS.pMsgFile = fopen(SMTPS.szMsgFile, "r+b")) == NULL) {
  1639. ErrSetErrorCode(ERR_FILE_OPEN, SMTPS.szMsgFile);
  1640. return (ERR_FILE_OPEN);
  1641. }
  1642. fseek(SMTPS.pMsgFile, 0, SEEK_END);
  1643. }
  1644. return (0);
  1645. }
  1646. static int SMTPHandleCmd_DATA(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  1647. {
  1648. char *pszError;
  1649. if (SMTPS.iSMTPState != stateRcpt) {
  1650. SMTPResetSession(SMTPS);
  1651. SMTPSendError(hBSock, SMTPS, "503 Bad sequence of commands");
  1652. ErrSetErrorCode(ERR_SMTP_BAD_CMD_SEQUENCE);
  1653. return (ERR_SMTP_BAD_CMD_SEQUENCE);
  1654. }
  1655. ///////////////////////////////////////////////////////////////////////////////
  1656. //  Run the pre-DATA filter
  1657. ///////////////////////////////////////////////////////////////////////////////
  1658. pszError = NULL;
  1659. if (SMTPFilterMessage(SMTPS, SMTP_PRE_DATA_FILTER, pszError) < 0) {
  1660. ErrorPush();
  1661. SMTPResetSession(SMTPS);
  1662. if (pszError != NULL) {
  1663. SMTPSendError(hBSock, SMTPS, "%s", pszError);
  1664. SysFree(pszError);
  1665. } else
  1666. BSckSendString(hBSock, "554 Transaction failed",
  1667.        SMTPS.pSMTPCfg->iTimeout);
  1668. return (ErrorPop());
  1669. }
  1670. ///////////////////////////////////////////////////////////////////////////////
  1671. //  Write data begin marker
  1672. ///////////////////////////////////////////////////////////////////////////////
  1673. if (StrWriteCRLFString(SMTPS.pMsgFile, SPOOL_FILE_DATA_START) < 0) {
  1674. ErrorPush();
  1675. SMTPResetSession(SMTPS);
  1676. SMTPSendError(hBSock, SMTPS,
  1677.       "451 Requested action aborted: (%d) local error in processing",
  1678.       ErrorFetch());
  1679. return (ErrorPop());
  1680. }
  1681. BSckSendString(hBSock, "354 Start mail input; end with <CRLF>.<CRLF>",
  1682.        SMTPS.pSMTPCfg->iTimeout);
  1683. ///////////////////////////////////////////////////////////////////////////////
  1684. //  Write data
  1685. ///////////////////////////////////////////////////////////////////////////////
  1686. int iErrorCode = 0;
  1687. int iLineLength;
  1688. int iGotNL;
  1689. int iGotNLPrev = 1;
  1690. unsigned long ulMessageSize = 0;
  1691. unsigned long ulMaxMsgSize = SMTPS.ulMaxMsgSize;
  1692. char const *pszSmtpError = NULL;
  1693. char szBuffer[SMTP_MAX_LINE_SIZE + 4];
  1694. for (;;) {
  1695. if (BSckGetString
  1696.     (hBSock, szBuffer, sizeof(szBuffer) - 3, SMTPS.pSMTPCfg->iTimeout,
  1697.      &iLineLength, &iGotNL) == NULL) {
  1698. ErrorPush();
  1699. SMTPResetSession(SMTPS);
  1700. return (ErrorPop());
  1701. }
  1702. ///////////////////////////////////////////////////////////////////////////////
  1703. //  Check end of data condition
  1704. ///////////////////////////////////////////////////////////////////////////////
  1705. if (iGotNL && iGotNLPrev && (strcmp(szBuffer, ".") == 0))
  1706. break;
  1707. ///////////////////////////////////////////////////////////////////////////////
  1708. //  Correctly terminate the line
  1709. ///////////////////////////////////////////////////////////////////////////////
  1710. if (iGotNL)
  1711. memcpy(szBuffer + iLineLength, "rn", 3), iLineLength += 2;
  1712. if (iErrorCode == 0) {
  1713. ///////////////////////////////////////////////////////////////////////////////
  1714. //  Write data on disk
  1715. ///////////////////////////////////////////////////////////////////////////////
  1716. if (!fwrite(szBuffer, iLineLength, 1, SMTPS.pMsgFile)) {
  1717. ErrSetErrorCode(iErrorCode = ERR_FILE_WRITE, SMTPS.szMsgFile);
  1718. }
  1719. }
  1720. ulMessageSize += (unsigned long) iLineLength;
  1721. ///////////////////////////////////////////////////////////////////////////////
  1722. //  Check the message size
  1723. ///////////////////////////////////////////////////////////////////////////////
  1724. if ((ulMaxMsgSize != 0) && (ulMaxMsgSize < ulMessageSize)) {
  1725. pszSmtpError = "552 Message exceeds fixed maximum message size";
  1726. ErrSetErrorCode(iErrorCode = ERR_MESSAGE_SIZE);
  1727. }
  1728. if (SvrInShutdown()) {
  1729. SMTPResetSession(SMTPS);
  1730. ErrSetErrorCode(ERR_SERVER_SHUTDOWN);
  1731. return (ERR_SERVER_SHUTDOWN);
  1732. }
  1733. iGotNLPrev = iGotNL;
  1734. }
  1735. ///////////////////////////////////////////////////////////////////////////////
  1736. //  Check fclose() return value coz data might be buffered and fail to flush
  1737. ///////////////////////////////////////////////////////////////////////////////
  1738. if (fclose(SMTPS.pMsgFile))
  1739. ErrSetErrorCode(iErrorCode = ERR_FILE_WRITE, SMTPS.szMsgFile);
  1740. SMTPS.pMsgFile = NULL;
  1741. if (iErrorCode == 0) {
  1742. ///////////////////////////////////////////////////////////////////////////////
  1743. //  Run the post-DATA filter
  1744. ///////////////////////////////////////////////////////////////////////////////
  1745. pszError = NULL;
  1746. if (SMTPFilterMessage(SMTPS, SMTP_POST_DATA_FILTER, pszError) < 0) {
  1747. ErrorPush();
  1748. SMTPResetSession(SMTPS);
  1749. if (pszError != NULL) {
  1750. SMTPSendError(hBSock, SMTPS, "%s", pszError);
  1751. SysFree(pszError);
  1752. } else
  1753. BSckSendString(hBSock, "554 Transaction failed",
  1754.        SMTPS.pSMTPCfg->iTimeout);
  1755. return (ErrorPop());
  1756. }
  1757. ///////////////////////////////////////////////////////////////////////////////
  1758. //  Transfer spool file
  1759. ///////////////////////////////////////////////////////////////////////////////
  1760. if (SMTPSubmitPackedFile(SMTPS, SMTPS.szMsgFile) < 0)
  1761. SMTPSendError(hBSock, SMTPS,
  1762.       "451 Requested action aborted: (%d) local error in processing",
  1763.       ErrGetErrorCode());
  1764. else {
  1765. ///////////////////////////////////////////////////////////////////////////////
  1766. //  Log the message receive
  1767. ///////////////////////////////////////////////////////////////////////////////
  1768. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  1769. SMTPLogSession(SMTPS, SMTPS.pszFrom, SMTPS.pszRcpt, "RECV=OK",
  1770.        ulMessageSize);
  1771. ///////////////////////////////////////////////////////////////////////////////
  1772. //  Send the ack only when everything is OK
  1773. ///////////////////////////////////////////////////////////////////////////////
  1774. BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout, "250 OK <%s>",
  1775. SMTPS.szMessageID);
  1776. }
  1777. } else {
  1778. ///////////////////////////////////////////////////////////////////////////////
  1779. //  Notify the client the error condition
  1780. ///////////////////////////////////////////////////////////////////////////////
  1781. if (pszSmtpError == NULL)
  1782. SMTPSendError(hBSock, SMTPS,
  1783.       "451 Requested action aborted: (%d) local error in processing",
  1784.       ErrGetErrorCode());
  1785. else
  1786. SMTPSendError(hBSock, SMTPS, "%s", pszSmtpError);
  1787. }
  1788. SMTPResetSession(SMTPS);
  1789. return (iErrorCode);
  1790. }
  1791. static int SMTPAddReceived(int iType, char const *pszAuth, char const *const *ppszMsgInfo,
  1792.    char const *pszMailFrom, char const *pszRcptTo,
  1793.    char const *pszMessageID, FILE * pMailFile)
  1794. {
  1795. char *pszReceived = USmtpGetReceived(iType, pszAuth, ppszMsgInfo, pszMailFrom, pszRcptTo,
  1796.      pszMessageID);
  1797. if (pszReceived == NULL)
  1798. return (ErrGetErrorCode());
  1799. ///////////////////////////////////////////////////////////////////////////////
  1800. //  Write "Received:" tag
  1801. ///////////////////////////////////////////////////////////////////////////////
  1802. fputs(pszReceived, pMailFile);
  1803. SysFree(pszReceived);
  1804. return (0);
  1805. }
  1806. static char *SMTPTrimRcptLine(char *pszRcptLn)
  1807. {
  1808. char *pszTrim = strchr(pszRcptLn, '>');
  1809. if (pszTrim != NULL)
  1810. pszTrim[1] = '';
  1811. return (pszRcptLn);
  1812. }
  1813. static int SMTPSubmitPackedFile(SMTPSession & SMTPS, const char *pszPkgFile)
  1814. {
  1815. FILE *pPkgFile = fopen(pszPkgFile, "rb");
  1816. if (pPkgFile == NULL) {
  1817. ErrSetErrorCode(ERR_FILE_OPEN);
  1818. return (ERR_FILE_OPEN);
  1819. }
  1820. char szSpoolLine[MAX_SPOOL_LINE] = "";
  1821. while ((MscGetString(pPkgFile, szSpoolLine, sizeof(szSpoolLine) - 1) != NULL) &&
  1822.        (strncmp(szSpoolLine, SPOOL_FILE_DATA_START, CStringSize(SPOOL_FILE_DATA_START)) !=
  1823. 0));
  1824. if (strncmp(szSpoolLine, SPOOL_FILE_DATA_START, CStringSize(SPOOL_FILE_DATA_START)) != 0) {
  1825. fclose(pPkgFile);
  1826. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  1827. return (ERR_INVALID_SPOOL_FILE);
  1828. }
  1829. ///////////////////////////////////////////////////////////////////////////////
  1830. //  Get the offset at which the message data begin and rewind the file
  1831. ///////////////////////////////////////////////////////////////////////////////
  1832. unsigned long ulMsgOffset = (unsigned long) ftell(pPkgFile);
  1833. rewind(pPkgFile);
  1834. ///////////////////////////////////////////////////////////////////////////////
  1835. //  Read SMTP message info ( 1st row of the smtp-mail file )
  1836. ///////////////////////////////////////////////////////////////////////////////
  1837. char **ppszMsgInfo = NULL;
  1838. if ((MscGetString(pPkgFile, szSpoolLine, sizeof(szSpoolLine) - 1) == NULL) ||
  1839.     ((ppszMsgInfo = StrTokenize(szSpoolLine, ";")) == NULL) ||
  1840.     (StrStringsCount(ppszMsgInfo) < smsgiMax)) {
  1841. if (ppszMsgInfo != NULL)
  1842. StrFreeStrings(ppszMsgInfo);
  1843. fclose(pPkgFile);
  1844. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  1845. return (ERR_INVALID_SPOOL_FILE);
  1846. }
  1847. ///////////////////////////////////////////////////////////////////////////////
  1848. //  Read SMTP domain ( 2nd row of the smtp-mail file )
  1849. ///////////////////////////////////////////////////////////////////////////////
  1850. char szSMTPDomain[256] = "";
  1851. if (MscGetString(pPkgFile, szSMTPDomain, sizeof(szSMTPDomain) - 1) == NULL) {
  1852. StrFreeStrings(ppszMsgInfo);
  1853. fclose(pPkgFile);
  1854. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  1855. return (ERR_INVALID_SPOOL_FILE);
  1856. }
  1857. ///////////////////////////////////////////////////////////////////////////////
  1858. //  Read message ID ( 3th row of the smtp-mail file )
  1859. ///////////////////////////////////////////////////////////////////////////////
  1860. char szMessageID[128] = "";
  1861. if (MscGetString(pPkgFile, szMessageID, sizeof(szMessageID) - 1) == NULL) {
  1862. StrFreeStrings(ppszMsgInfo);
  1863. fclose(pPkgFile);
  1864. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  1865. return (ERR_INVALID_SPOOL_FILE);
  1866. }
  1867. ///////////////////////////////////////////////////////////////////////////////
  1868. //  Read "MAIL FROM:" ( 4th row of the smtp-mail file )
  1869. ///////////////////////////////////////////////////////////////////////////////
  1870. char szMailFrom[MAX_SPOOL_LINE] = "";
  1871. if ((MscGetString(pPkgFile, szMailFrom, sizeof(szMailFrom) - 1) == NULL) ||
  1872.     (StrINComp(szMailFrom, MAIL_FROM_STR) != 0)) {
  1873. StrFreeStrings(ppszMsgInfo);
  1874. fclose(pPkgFile);
  1875. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  1876. return (ERR_INVALID_SPOOL_FILE);
  1877. }
  1878. ///////////////////////////////////////////////////////////////////////////////
  1879. //  Get the Received: header type to emit
  1880. ///////////////////////////////////////////////////////////////////////////////
  1881. int iReceivedType = SvrGetConfigInt("ReceivedHdrType", RECEIVED_TYPE_STD,
  1882.     SMTPS.hSvrConfig);
  1883. ///////////////////////////////////////////////////////////////////////////////
  1884. //  Read "RCPT TO:" ( 5th[,...] row(s) of the smtp-mail file )
  1885. ///////////////////////////////////////////////////////////////////////////////
  1886. while ((MscGetString(pPkgFile, szSpoolLine, sizeof(szSpoolLine) - 1) != NULL) &&
  1887.        (StrINComp(szSpoolLine, RCPT_TO_STR) == 0)) {
  1888. ///////////////////////////////////////////////////////////////////////////////
  1889. //  Cleanup the RCPT line from extra info
  1890. ///////////////////////////////////////////////////////////////////////////////
  1891. SMTPTrimRcptLine(szSpoolLine);
  1892. ///////////////////////////////////////////////////////////////////////////////
  1893. //  Get message handle
  1894. ///////////////////////////////////////////////////////////////////////////////
  1895. QMSG_HANDLE hMessage = QueCreateMessage(hSpoolQueue);
  1896. if (hMessage == INVALID_QMSG_HANDLE) {
  1897. ErrorPush();
  1898. StrFreeStrings(ppszMsgInfo);
  1899. fclose(pPkgFile);
  1900. return (ErrorPop());
  1901. }
  1902. char szQueueFilePath[SYS_MAX_PATH] = "";
  1903. QueGetFilePath(hSpoolQueue, hMessage, szQueueFilePath);
  1904. FILE *pSpoolFile = fopen(szQueueFilePath, "wb");
  1905. if (pSpoolFile == NULL) {
  1906. QueCleanupMessage(hSpoolQueue, hMessage);
  1907. QueCloseMessage(hSpoolQueue, hMessage);
  1908. StrFreeStrings(ppszMsgInfo);
  1909. fclose(pPkgFile);
  1910. ErrSetErrorCode(ERR_FILE_CREATE);
  1911. return (ERR_FILE_CREATE);
  1912. }
  1913. ///////////////////////////////////////////////////////////////////////////////
  1914. //  Write info line
  1915. ///////////////////////////////////////////////////////////////////////////////
  1916. USmtpWriteInfoLine(pSpoolFile, ppszMsgInfo[smsgiClientAddr],
  1917.    ppszMsgInfo[smsgiServerAddr], ppszMsgInfo[smsgiTime]);
  1918. ///////////////////////////////////////////////////////////////////////////////
  1919. //  Write SMTP domain
  1920. ///////////////////////////////////////////////////////////////////////////////
  1921. fprintf(pSpoolFile, "%srn", szSMTPDomain);
  1922. ///////////////////////////////////////////////////////////////////////////////
  1923. //  Write message ID
  1924. ///////////////////////////////////////////////////////////////////////////////
  1925. fprintf(pSpoolFile, "%srn", szMessageID);
  1926. ///////////////////////////////////////////////////////////////////////////////
  1927. //  Write "MAIL FROM:"
  1928. ///////////////////////////////////////////////////////////////////////////////
  1929. fprintf(pSpoolFile, "%srn", szMailFrom);
  1930. ///////////////////////////////////////////////////////////////////////////////
  1931. //  Write "RCPT TO:"
  1932. ///////////////////////////////////////////////////////////////////////////////
  1933. fprintf(pSpoolFile, "%srn", szSpoolLine);
  1934. ///////////////////////////////////////////////////////////////////////////////
  1935. //  Write SPOOL_FILE_DATA_START
  1936. ///////////////////////////////////////////////////////////////////////////////
  1937. fprintf(pSpoolFile, "%srn", SPOOL_FILE_DATA_START);
  1938. ///////////////////////////////////////////////////////////////////////////////
  1939. //  Write "X-AuthUser:" tag
  1940. ///////////////////////////////////////////////////////////////////////////////
  1941. if (!IsEmptyString(SMTPS.szLogonUser) && !(SMTPS.ulFlags & SMTPF_NOEMIT_AUTH))
  1942. fprintf(pSpoolFile, "X-AuthUser: %srn", SMTPS.szLogonUser);
  1943. ///////////////////////////////////////////////////////////////////////////////
  1944. //  Write "Received:" tag
  1945. ///////////////////////////////////////////////////////////////////////////////
  1946. SMTPAddReceived(iReceivedType,
  1947. IsEmptyString(SMTPS.szLogonUser) ? NULL : SMTPS.szLogonUser,
  1948. ppszMsgInfo, szMailFrom, szSpoolLine, szMessageID, pSpoolFile);
  1949. ///////////////////////////////////////////////////////////////////////////////
  1950. //  Write mail data, saving and restoring the current file pointer
  1951. ///////////////////////////////////////////////////////////////////////////////
  1952. unsigned long ulCurrOffset = (unsigned long) ftell(pPkgFile);
  1953. if (MscCopyFile(pSpoolFile, pPkgFile, ulMsgOffset, (unsigned long) -1) < 0) {
  1954. ErrorPush();
  1955. fclose(pSpoolFile);
  1956. QueCleanupMessage(hSpoolQueue, hMessage);
  1957. QueCloseMessage(hSpoolQueue, hMessage);
  1958. StrFreeStrings(ppszMsgInfo);
  1959. fclose(pPkgFile);
  1960. return (ErrorPop());
  1961. }
  1962. if (SysFileSync(pSpoolFile) < 0) {
  1963. ErrorPush();
  1964. fclose(pSpoolFile);
  1965. QueCleanupMessage(hSpoolQueue, hMessage);
  1966. QueCloseMessage(hSpoolQueue, hMessage);
  1967. StrFreeStrings(ppszMsgInfo);
  1968. fclose(pPkgFile);
  1969. return (ErrorPop());
  1970. }
  1971. if (fclose(pSpoolFile)) {
  1972. QueCleanupMessage(hSpoolQueue, hMessage);
  1973. QueCloseMessage(hSpoolQueue, hMessage);
  1974. StrFreeStrings(ppszMsgInfo);
  1975. fclose(pPkgFile);
  1976. ErrSetErrorCode(ERR_FILE_WRITE, szQueueFilePath);
  1977. return (ERR_FILE_WRITE);
  1978. }
  1979. fseek(pPkgFile, ulCurrOffset, SEEK_SET);
  1980. ///////////////////////////////////////////////////////////////////////////////
  1981. //  Transfer file to the spool
  1982. ///////////////////////////////////////////////////////////////////////////////
  1983. if (QueCommitMessage(hSpoolQueue, hMessage) < 0) {
  1984. ErrorPush();
  1985. QueCleanupMessage(hSpoolQueue, hMessage);
  1986. QueCloseMessage(hSpoolQueue, hMessage);
  1987. StrFreeStrings(ppszMsgInfo);
  1988. fclose(pPkgFile);
  1989. return (ErrorPop());
  1990. }
  1991. }
  1992. StrFreeStrings(ppszMsgInfo);
  1993. fclose(pPkgFile);
  1994. return (0);
  1995. }
  1996. static int SMTPHandleCmd_HELO(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  1997. {
  1998. if ((SMTPS.iSMTPState != stateInit) && (SMTPS.iSMTPState != stateHelo)) {
  1999. SMTPResetSession(SMTPS);
  2000. SMTPSendError(hBSock, SMTPS, "503 Bad sequence of commands");
  2001. ErrSetErrorCode(ERR_SMTP_BAD_CMD_SEQUENCE);
  2002. return (ERR_SMTP_BAD_CMD_SEQUENCE);
  2003. }
  2004. char **ppszTokens = StrTokenize(pszCommand, " ");
  2005. if ((ppszTokens == NULL) || (StrStringsCount(ppszTokens) != 2)) {
  2006. if (ppszTokens != NULL)
  2007. StrFreeStrings(ppszTokens);
  2008. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2009. return (-1);
  2010. }
  2011. StrSNCpy(SMTPS.szClientDomain, ppszTokens[1]);
  2012. StrFreeStrings(ppszTokens);
  2013. char *pszDomain = SvrGetConfigVar(SMTPS.hSvrConfig, "RootDomain");
  2014. if (pszDomain == NULL) {
  2015. SMTPSendError(hBSock, SMTPS,
  2016.       "451 Requested action aborted: (%d) local error in processing",
  2017.       ERR_NO_ROOT_DOMAIN_VAR);
  2018. ErrSetErrorCode(ERR_NO_ROOT_DOMAIN_VAR);
  2019. return (ERR_NO_ROOT_DOMAIN_VAR);
  2020. }
  2021. BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout, "250 %s", pszDomain);
  2022. SysFree(pszDomain);
  2023. SMTPS.iSMTPState = stateHelo;
  2024. return (0);
  2025. }
  2026. static int SMTPHandleCmd_EHLO(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  2027. {
  2028. if ((SMTPS.iSMTPState != stateInit) && (SMTPS.iSMTPState != stateHelo)) {
  2029. SMTPResetSession(SMTPS);
  2030. SMTPSendError(hBSock, SMTPS, "503 Bad sequence of commands");
  2031. ErrSetErrorCode(ERR_SMTP_BAD_CMD_SEQUENCE);
  2032. return (ERR_SMTP_BAD_CMD_SEQUENCE);
  2033. }
  2034. char **ppszTokens = StrTokenize(pszCommand, " ");
  2035. if ((ppszTokens == NULL) || (StrStringsCount(ppszTokens) != 2)) {
  2036. if (ppszTokens != NULL)
  2037. StrFreeStrings(ppszTokens);
  2038. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2039. return (-1);
  2040. }
  2041. StrSNCpy(SMTPS.szClientDomain, ppszTokens[1]);
  2042. StrFreeStrings(ppszTokens);
  2043. ///////////////////////////////////////////////////////////////////////////////
  2044. //  Create response file
  2045. ///////////////////////////////////////////////////////////////////////////////
  2046. char szRespFile[SYS_MAX_PATH] = "";
  2047. SysGetTmpFile(szRespFile);
  2048. FILE *pRespFile = fopen(szRespFile, "w+b");
  2049. if (pRespFile == NULL) {
  2050. CheckRemoveFile(szRespFile);
  2051. SMTPSendError(hBSock, SMTPS,
  2052.       "451 Requested action aborted: (%d) local error in processing",
  2053.       ERR_FILE_CREATE);
  2054. ErrSetErrorCode(ERR_FILE_CREATE);
  2055. return (ERR_FILE_CREATE);
  2056. }
  2057. ///////////////////////////////////////////////////////////////////////////////
  2058. //  Get root domain ( "RootDomain" )
  2059. ///////////////////////////////////////////////////////////////////////////////
  2060. char *pszDomain = SvrGetConfigVar(SMTPS.hSvrConfig, "RootDomain");
  2061. if (pszDomain == NULL) {
  2062. fclose(pRespFile);
  2063. SysRemove(szRespFile);
  2064. SMTPSendError(hBSock, SMTPS,
  2065.       "451 Requested action aborted: (%d) local error in processing",
  2066.       ERR_NO_ROOT_DOMAIN_VAR);
  2067. ErrSetErrorCode(ERR_NO_ROOT_DOMAIN_VAR);
  2068. return (ERR_NO_ROOT_DOMAIN_VAR);
  2069. }
  2070. ///////////////////////////////////////////////////////////////////////////////
  2071. //  Build EHLO response file ( domain + auths )
  2072. ///////////////////////////////////////////////////////////////////////////////
  2073. fprintf(pRespFile, "250 %srn", pszDomain);
  2074. SysFree(pszDomain);
  2075. ///////////////////////////////////////////////////////////////////////////////
  2076. //  Emit extended SMTP command and internal auths
  2077. ///////////////////////////////////////////////////////////////////////////////
  2078. fprintf(pRespFile,
  2079. "250 VRFYrn"
  2080. "250 ETRNrn"
  2081. "250 8BITMIMErn" "250 PIPELININGrn" "250 AUTH LOGIN PLAIN CRAM-MD5");
  2082. ///////////////////////////////////////////////////////////////////////////////
  2083. //  Emit external authentication methods
  2084. ///////////////////////////////////////////////////////////////////////////////
  2085. SMTPListExtAuths(pRespFile, SMTPS);
  2086. fprintf(pRespFile, "rn");
  2087. ///////////////////////////////////////////////////////////////////////////////
  2088. //  Emit maximum message size ( if set )
  2089. ///////////////////////////////////////////////////////////////////////////////
  2090. if (SMTPS.ulMaxMsgSize != 0)
  2091. fprintf(pRespFile, "250 SIZE %lurn", SMTPS.ulMaxMsgSize);
  2092. else
  2093. fprintf(pRespFile, "250 SIZErn");
  2094. ///////////////////////////////////////////////////////////////////////////////
  2095. //  Send EHLO response file
  2096. ///////////////////////////////////////////////////////////////////////////////
  2097. if (SMTPSendMultilineResponse(hBSock, SMTPS.pSMTPCfg->iTimeout, pRespFile) < 0) {
  2098. ErrorPush();
  2099. fclose(pRespFile);
  2100. SysRemove(szRespFile);
  2101. SMTPSendError(hBSock, SMTPS,
  2102.       "451 Requested action aborted: (%d) local error in processing",
  2103.       ErrorFetch());
  2104. return (ErrorPop());
  2105. }
  2106. fclose(pRespFile);
  2107. SysRemove(szRespFile);
  2108. SMTPS.iSMTPState = stateHelo;
  2109. return (0);
  2110. }
  2111. static int SMTPListExtAuths(FILE * pRespFile, SMTPSession & SMTPS)
  2112. {
  2113. char szExtAuthFilePath[SYS_MAX_PATH] = "";
  2114. SMTPGetExtAuthFilePath(szExtAuthFilePath, sizeof(szExtAuthFilePath));
  2115. FILE *pExtAuthFile = fopen(szExtAuthFilePath, "rt");
  2116. if (pExtAuthFile != NULL) {
  2117. char szExtAuthLine[SVR_SMTP_EXTAUTH_LINE_MAX] = "";
  2118. while (MscGetConfigLine(szExtAuthLine, sizeof(szExtAuthLine) - 1, pExtAuthFile) !=
  2119.        NULL) {
  2120. char **ppszStrings = StrGetTabLineStrings(szExtAuthLine);
  2121. if (ppszStrings == NULL)
  2122. continue;
  2123. if (StrStringsCount(ppszStrings) > 0)
  2124. fprintf(pRespFile, " %s", ppszStrings[0]);
  2125. StrFreeStrings(ppszStrings);
  2126. }
  2127. fclose(pExtAuthFile);
  2128. }
  2129. return (0);
  2130. }
  2131. static int SMTPExternalAuthSubstitute(char **ppszAuthTokens, char const *pszChallenge,
  2132.       char const *pszDigest, char const *pszSecretsFile)
  2133. {
  2134. for (int ii = 0; ppszAuthTokens[ii] != NULL; ii++) {
  2135. if (strcmp(ppszAuthTokens[ii], "@@FSECRT") == 0) {
  2136. char *pszNewValue = SysStrDup(pszSecretsFile);
  2137. if (pszNewValue == NULL)
  2138. return (ErrGetErrorCode());
  2139. SysFree(ppszAuthTokens[ii]);
  2140. ppszAuthTokens[ii] = pszNewValue;
  2141. } else if (strcmp(ppszAuthTokens[ii], "@@CHALL") == 0) {
  2142. char *pszNewValue = SysStrDup(pszChallenge);
  2143. if (pszNewValue == NULL)
  2144. return (ErrGetErrorCode());
  2145. SysFree(ppszAuthTokens[ii]);
  2146. ppszAuthTokens[ii] = pszNewValue;
  2147. } else if (strcmp(ppszAuthTokens[ii], "@@DGEST") == 0) {
  2148. char *pszNewValue = SysStrDup(pszDigest);
  2149. if (pszNewValue == NULL)
  2150. return (ErrGetErrorCode());
  2151. SysFree(ppszAuthTokens[ii]);
  2152. ppszAuthTokens[ii] = pszNewValue;
  2153. }
  2154. }
  2155. return (0);
  2156. }
  2157. static int SMTPCreateSecretsFile(char const *pszSecretsFile)
  2158. {
  2159. char szAuthFilePath[SYS_MAX_PATH] = "";
  2160. SMTPGetAuthFilePath(szAuthFilePath, sizeof(szAuthFilePath));
  2161. FILE *pAuthFile = fopen(szAuthFilePath, "rt");
  2162. if (pAuthFile == NULL) {
  2163. ErrSetErrorCode(ERR_FILE_OPEN, szAuthFilePath);
  2164. return (ERR_FILE_OPEN);
  2165. }
  2166. FILE *pSecretFile = fopen(pszSecretsFile, "wt");
  2167. if (pSecretFile == NULL) {
  2168. fclose(pAuthFile);
  2169. ErrSetErrorCode(ERR_FILE_CREATE, pszSecretsFile);
  2170. return (ERR_FILE_CREATE);
  2171. }
  2172. char szAuthLine[SVR_SMTPAUTH_LINE_MAX] = "";
  2173. while (MscGetConfigLine(szAuthLine, sizeof(szAuthLine) - 1, pAuthFile) != NULL) {
  2174. char **ppszStrings = StrGetTabLineStrings(szAuthLine);
  2175. if (ppszStrings == NULL)
  2176. continue;
  2177. int iFieldsCount = StrStringsCount(ppszStrings);
  2178. if (iFieldsCount >= smtpaMax)
  2179. fprintf(pSecretFile, "%s:%sn", ppszStrings[smtpaUsername],
  2180. ppszStrings[smtpaPassword]);
  2181. StrFreeStrings(ppszStrings);
  2182. }
  2183. fclose(pSecretFile);
  2184. fclose(pAuthFile);
  2185. return (0);
  2186. }
  2187. static int SMTPExternalAuthenticate(BSOCK_HANDLE hBSock, SMTPSession & SMTPS,
  2188.     char **ppszAuthTokens)
  2189. {
  2190. ///////////////////////////////////////////////////////////////////////////////
  2191. //  Emit encoded ( base64 ) challenge ( param1 + ':' + timestamp )
  2192. //  and get client response
  2193. ///////////////////////////////////////////////////////////////////////////////
  2194. unsigned int uEnc64Length = 0;
  2195. char szChallenge[1024] = "";
  2196. char szDigest[1024] = "";
  2197. SysSNPrintf(szDigest, sizeof(szDigest) - 1, "%s:%s", ppszAuthTokens[1],
  2198.     SMTPS.szTimeStamp);
  2199. encode64(szDigest, strlen(szDigest), szChallenge, sizeof(szChallenge) - 1, &uEnc64Length);
  2200. if ((BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout, "334 %s", szChallenge) < 0) ||
  2201.     (BSckGetString(hBSock, szChallenge, sizeof(szChallenge) - 1, SMTPS.pSMTPCfg->iTimeout)
  2202.      == NULL))
  2203. return (ErrGetErrorCode());
  2204. ///////////////////////////////////////////////////////////////////////////////
  2205. //  Decode ( base64 ) client response
  2206. ///////////////////////////////////////////////////////////////////////////////
  2207. unsigned int uDec64Length = 0;
  2208. if (decode64(szChallenge, strlen(szChallenge), szDigest, &uDec64Length) != 0) {
  2209. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2210. ErrSetErrorCode(ERR_BAD_SMTP_CMD_SYNTAX);
  2211. return (ERR_BAD_SMTP_CMD_SYNTAX);
  2212. }
  2213. SysSNPrintf(szChallenge, sizeof(szChallenge) - 1, "%s:%s", ppszAuthTokens[1],
  2214.     SMTPS.szTimeStamp);
  2215. ///////////////////////////////////////////////////////////////////////////////
  2216. //  Create secrets file ( username + ':' + password )
  2217. ///////////////////////////////////////////////////////////////////////////////
  2218. char szSecretsFile[SYS_MAX_PATH] = "";
  2219. SysGetTmpFile(szSecretsFile);
  2220. if (SMTPCreateSecretsFile(szSecretsFile) < 0) {
  2221. ErrorPush();
  2222. CheckRemoveFile(szSecretsFile);
  2223. return (ErrorPop());
  2224. }
  2225. ///////////////////////////////////////////////////////////////////////////////
  2226. //  Do macro substitution
  2227. ///////////////////////////////////////////////////////////////////////////////
  2228. SMTPExternalAuthSubstitute(ppszAuthTokens, szChallenge, szDigest, szSecretsFile);
  2229. ///////////////////////////////////////////////////////////////////////////////
  2230. //  Call external program to compute the response
  2231. ///////////////////////////////////////////////////////////////////////////////
  2232. int iExitCode = -1;
  2233. if (SysExec(ppszAuthTokens[2], &ppszAuthTokens[2], SVR_SMTP_EXTAUTH_TIMEOUT,
  2234.     SVR_SMTP_EXTAUTH_PRIORITY, &iExitCode) < 0) {
  2235. ErrorPush();
  2236. SysRemove(szSecretsFile);
  2237. SMTPSendError(hBSock, SMTPS,
  2238.       "451 Requested action aborted: (%d) local error in processing",
  2239.       ErrorFetch());
  2240. return (ErrorPop());
  2241. }
  2242. if (iExitCode != SVR_SMTP_EXTAUTH_SUCCESS) {
  2243. SysRemove(szSecretsFile);
  2244. SMTPSendError(hBSock, SMTPS, "503 Authentication failed");
  2245. ErrSetErrorCode(ERR_BAD_EXTRNPRG_EXITCODE);
  2246. return (ERR_BAD_EXTRNPRG_EXITCODE);
  2247. }
  2248. ///////////////////////////////////////////////////////////////////////////////
  2249. //  Load response file containing the matching secret
  2250. ///////////////////////////////////////////////////////////////////////////////
  2251. unsigned int uRespSize = 0;
  2252. char *pMatchSecret = (char *) MscLoadFile(szSecretsFile, uRespSize);
  2253. CheckRemoveFile(szSecretsFile);
  2254. if (pMatchSecret == NULL) {
  2255. ErrorPush();
  2256. SMTPSendError(hBSock, SMTPS,
  2257.       "451 Requested action aborted: (%d) local error in processing",
  2258.       ErrorFetch());
  2259. return (ErrorPop());
  2260. }
  2261. while ((uRespSize > 0) &&
  2262.        ((pMatchSecret[uRespSize - 1] == 'r') || (pMatchSecret[uRespSize - 1] == 'n')))
  2263. --uRespSize;
  2264. pMatchSecret[uRespSize] = '';
  2265. ///////////////////////////////////////////////////////////////////////////////
  2266. //  Try to extract username and password tokens ( username + ':' + password )
  2267. ///////////////////////////////////////////////////////////////////////////////
  2268. char **ppszTokens = StrTokenize(pMatchSecret, ":");
  2269. SysFree(pMatchSecret);
  2270. if (StrStringsCount(ppszTokens) != 2) {
  2271. StrFreeStrings(ppszTokens);
  2272. SMTPSendError(hBSock, SMTPS,
  2273.       "451 Requested action aborted: (%d) local error in processing",
  2274.       ERR_BAD_SMTP_EXTAUTH_RESPONSE_FILE);
  2275. ErrSetErrorCode(ERR_BAD_SMTP_EXTAUTH_RESPONSE_FILE);
  2276. return (ERR_BAD_SMTP_EXTAUTH_RESPONSE_FILE);
  2277. }
  2278. ///////////////////////////////////////////////////////////////////////////////
  2279. //  Lookup smtp auth file
  2280. ///////////////////////////////////////////////////////////////////////////////
  2281. if (SMTPTryApplyUsrPwdAuth(SMTPS, ppszTokens[0], ppszTokens[1]) < 0) {
  2282. ErrorPush();
  2283. StrFreeStrings(ppszTokens);
  2284. SMTPSendError(hBSock, SMTPS, "503 Authentication failed");
  2285. return (ErrorPop());
  2286. }
  2287. ///////////////////////////////////////////////////////////////////////////////
  2288. //  Set the logon user
  2289. ///////////////////////////////////////////////////////////////////////////////
  2290. StrSNCpy(SMTPS.szLogonUser, ppszTokens[0]);
  2291. StrFreeStrings(ppszTokens);
  2292. SMTPS.ulFlags |= SMTPF_AUTHENTICATED;
  2293. SMTPS.iSMTPState = stateAuthenticated;
  2294. BSckSendString(hBSock, "235 Authentication successful", SMTPS.pSMTPCfg->iTimeout);
  2295. return (0);
  2296. }
  2297. static int SMTPDoAuthExternal(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszAuthType)
  2298. {
  2299. char szExtAuthFilePath[SYS_MAX_PATH] = "";
  2300. SMTPGetExtAuthFilePath(szExtAuthFilePath, sizeof(szExtAuthFilePath));
  2301. FILE *pExtAuthFile = fopen(szExtAuthFilePath, "rt");
  2302. if (pExtAuthFile == NULL) {
  2303. ErrSetErrorCode(ERR_FILE_OPEN, szExtAuthFilePath);
  2304. return (ERR_FILE_OPEN);
  2305. }
  2306. char szExtAuthLine[SVR_SMTP_EXTAUTH_LINE_MAX] = "";
  2307. while (MscGetConfigLine(szExtAuthLine, sizeof(szExtAuthLine) - 1, pExtAuthFile) != NULL) {
  2308. char **ppszStrings = StrGetTabLineStrings(szExtAuthLine);
  2309. if (ppszStrings == NULL)
  2310. continue;
  2311. int iFieldsCount = StrStringsCount(ppszStrings);
  2312. if ((iFieldsCount > 5) && (stricmp(ppszStrings[0], pszAuthType) == 0)) {
  2313. fclose(pExtAuthFile);
  2314. int iAuthResult = SMTPExternalAuthenticate(hBSock, SMTPS, ppszStrings);
  2315. StrFreeStrings(ppszStrings);
  2316. return (iAuthResult);
  2317. }
  2318. StrFreeStrings(ppszStrings);
  2319. }
  2320. fclose(pExtAuthFile);
  2321. SMTPSendError(hBSock, SMTPS, "504 Unknown authentication");
  2322. ErrSetErrorCode(ERR_UNKNOWN_SMTP_AUTH, pszAuthType);
  2323. return (ERR_UNKNOWN_SMTP_AUTH);
  2324. }
  2325. static int SMTPDoAuthPlain(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszAuthParam)
  2326. {
  2327. ///////////////////////////////////////////////////////////////////////////////
  2328. //  Parameter validation
  2329. ///////////////////////////////////////////////////////////////////////////////
  2330. if ((pszAuthParam == NULL) || (strlen(pszAuthParam) == 0)) {
  2331. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2332. ErrSetErrorCode(ERR_BAD_SMTP_CMD_SYNTAX);
  2333. return (ERR_BAD_SMTP_CMD_SYNTAX);
  2334. }
  2335. ///////////////////////////////////////////////////////////////////////////////
  2336. //  Decode ( base64 ) auth parameter
  2337. ///////////////////////////////////////////////////////////////////////////////
  2338. unsigned int uDec64Length = 0;
  2339. char szClientAuth[PLAIN_AUTH_PARAM_SIZE] = "";
  2340. ZeroData(szClientAuth);
  2341. if (decode64(pszAuthParam, strlen(pszAuthParam), szClientAuth, &uDec64Length) != 0) {
  2342. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2343. ErrSetErrorCode(ERR_BAD_SMTP_CMD_SYNTAX);
  2344. return (ERR_BAD_SMTP_CMD_SYNTAX);
  2345. }
  2346. ///////////////////////////////////////////////////////////////////////////////
  2347. //  Extract plain auth params ( unused + 0 + username + 0 + password )
  2348. ///////////////////////////////////////////////////////////////////////////////
  2349. char *pszUsername = szClientAuth + strlen(szClientAuth) + 1;
  2350. char *pszPassword = pszUsername + strlen(pszUsername) + 1;
  2351. ///////////////////////////////////////////////////////////////////////////////
  2352. //  Validate client response
  2353. ///////////////////////////////////////////////////////////////////////////////
  2354. if ((SMTPTryApplyLocalAuth(SMTPS, pszUsername, pszPassword) < 0) &&
  2355.     (SMTPTryApplyUsrPwdAuth(SMTPS, pszUsername, pszPassword) < 0)) {
  2356. ErrorPush();
  2357. SMTPSendError(hBSock, SMTPS, "503 Authentication failed");
  2358. return (ErrorPop());
  2359. }
  2360. ///////////////////////////////////////////////////////////////////////////////
  2361. //  Set the logon user
  2362. ///////////////////////////////////////////////////////////////////////////////
  2363. StrSNCpy(SMTPS.szLogonUser, pszUsername);
  2364. SMTPS.ulFlags |= SMTPF_AUTHENTICATED;
  2365. SMTPS.iSMTPState = stateAuthenticated;
  2366. BSckSendString(hBSock, "235 Authentication successful", SMTPS.pSMTPCfg->iTimeout);
  2367. return (0);
  2368. }
  2369. static int SMTPDoAuthLogin(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszAuthParam)
  2370. {
  2371. ///////////////////////////////////////////////////////////////////////////////
  2372. //  Emit encoded64 username request
  2373. ///////////////////////////////////////////////////////////////////////////////
  2374. unsigned int uEnc64Length = 0;
  2375. char szUsername[512] = "";
  2376. encode64(LOGIN_AUTH_USERNAME, strlen(LOGIN_AUTH_USERNAME), szUsername,
  2377.  sizeof(szUsername), &uEnc64Length);
  2378. if ((BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout, "334 %s", szUsername) < 0) ||
  2379.     (BSckGetString(hBSock, szUsername, sizeof(szUsername) - 1, SMTPS.pSMTPCfg->iTimeout)
  2380.      == NULL))
  2381. return (ErrGetErrorCode());
  2382. ///////////////////////////////////////////////////////////////////////////////
  2383. //  Emit encoded64 password request
  2384. ///////////////////////////////////////////////////////////////////////////////
  2385. char szPassword[512] = "";
  2386. encode64(LOGIN_AUTH_PASSWORD, strlen(LOGIN_AUTH_PASSWORD), szPassword,
  2387.  sizeof(szPassword), &uEnc64Length);
  2388. if ((BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout, "334 %s", szPassword) < 0) ||
  2389.     (BSckGetString(hBSock, szPassword, sizeof(szPassword) - 1, SMTPS.pSMTPCfg->iTimeout)
  2390.      == NULL))
  2391. return (ErrGetErrorCode());
  2392. ///////////////////////////////////////////////////////////////////////////////
  2393. //  Decode ( base64 ) username
  2394. ///////////////////////////////////////////////////////////////////////////////
  2395. unsigned int uDec64Length = 0;
  2396. char szDecodeBuffer[512] = "";
  2397. if (decode64(szUsername, strlen(szUsername), szDecodeBuffer, &uDec64Length) != 0) {
  2398. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2399. ErrSetErrorCode(ERR_BAD_SMTP_CMD_SYNTAX);
  2400. return (ERR_BAD_SMTP_CMD_SYNTAX);
  2401. }
  2402. StrSNCpy(szUsername, szDecodeBuffer);
  2403. ///////////////////////////////////////////////////////////////////////////////
  2404. //  Decode ( base64 ) password
  2405. ///////////////////////////////////////////////////////////////////////////////
  2406. if (decode64(szPassword, strlen(szPassword), szDecodeBuffer, &uDec64Length) != 0) {
  2407. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2408. ErrSetErrorCode(ERR_BAD_SMTP_CMD_SYNTAX);
  2409. return (ERR_BAD_SMTP_CMD_SYNTAX);
  2410. }
  2411. StrSNCpy(szPassword, szDecodeBuffer);
  2412. ///////////////////////////////////////////////////////////////////////////////
  2413. //  Validate client response
  2414. ///////////////////////////////////////////////////////////////////////////////
  2415. if ((SMTPTryApplyLocalAuth(SMTPS, szUsername, szPassword) < 0) &&
  2416.     (SMTPTryApplyUsrPwdAuth(SMTPS, szUsername, szPassword) < 0)) {
  2417. ErrorPush();
  2418. SMTPSendError(hBSock, SMTPS, "503 Authentication failed");
  2419. return (ErrorPop());
  2420. }
  2421. ///////////////////////////////////////////////////////////////////////////////
  2422. //  Set the logon user
  2423. ///////////////////////////////////////////////////////////////////////////////
  2424. StrSNCpy(SMTPS.szLogonUser, szUsername);
  2425. SMTPS.ulFlags |= SMTPF_AUTHENTICATED;
  2426. SMTPS.iSMTPState = stateAuthenticated;
  2427. BSckSendString(hBSock, "235 Authentication successful", SMTPS.pSMTPCfg->iTimeout);
  2428. return (0);
  2429. }
  2430. static char *SMTPGetAuthFilePath(char *pszFilePath, int iMaxPath)
  2431. {
  2432. CfgGetRootPath(pszFilePath, iMaxPath);
  2433. StrNCat(pszFilePath, SVR_SMTP_AUTH_FILE, iMaxPath);
  2434. return (pszFilePath);
  2435. }
  2436. static char *SMTPGetExtAuthFilePath(char *pszFilePath, int iMaxPath)
  2437. {
  2438. CfgGetRootPath(pszFilePath, iMaxPath);
  2439. StrNCat(pszFilePath, SVR_SMTP_EXTAUTH_FILE, iMaxPath);
  2440. return (pszFilePath);
  2441. }
  2442. static int SMTPTryApplyLocalAuth(SMTPSession & SMTPS, char const *pszUsername,
  2443.  char const *pszPassword)
  2444. {
  2445. ///////////////////////////////////////////////////////////////////////////////
  2446. //  First try to lookup  mailusers.tab
  2447. ///////////////////////////////////////////////////////////////////////////////
  2448. char szAccountUser[MAX_ADDR_NAME] = "";
  2449. char szAccountDomain[MAX_HOST_NAME] = "";
  2450. if (StrSplitString(pszUsername, POP3_USER_SPLITTERS, szAccountUser, sizeof(szAccountUser),
  2451.    szAccountDomain, sizeof(szAccountDomain)) < 0)
  2452. return (ErrGetErrorCode());
  2453. UserInfo *pUI = UsrGetUserByName(szAccountDomain, szAccountUser);
  2454. if (pUI != NULL) {
  2455. if (strcmp(pUI->pszPassword, pszPassword) == 0) {
  2456. ///////////////////////////////////////////////////////////////////////////////
  2457. //  Apply user configuration
  2458. ///////////////////////////////////////////////////////////////////////////////
  2459. if (SMTPApplyUserConfig(SMTPS, pUI) < 0) {
  2460. ErrorPush();
  2461. UsrFreeUserInfo(pUI);
  2462. return (ErrorPop());
  2463. }
  2464. UsrFreeUserInfo(pUI);
  2465. return (0);
  2466. }
  2467. UsrFreeUserInfo(pUI);
  2468. }
  2469. ErrSetErrorCode(ERR_SMTP_AUTH_FAILED);
  2470. return (ERR_SMTP_AUTH_FAILED);
  2471. }
  2472. static int SMTPGetUserSmtpPerms(UserInfo * pUI, SVRCFG_HANDLE hSvrConfig, char *pszPerms,
  2473. int iMaxPerms)
  2474. {
  2475. char *pszUserPerms = UsrGetUserInfoVar(pUI, "SmtpPerms");
  2476. if (pszUserPerms != NULL) {
  2477. StrNCpy(pszPerms, pszUserPerms, iMaxPerms);
  2478. SysFree(pszUserPerms);
  2479. } else {
  2480. ///////////////////////////////////////////////////////////////////////////////
  2481. //  Match found, get the default permissions
  2482. ///////////////////////////////////////////////////////////////////////////////
  2483. char *pszDefultPerms = SvrGetConfigVar(hSvrConfig,
  2484.        "DefaultSmtpPerms", "MR");
  2485. if (pszDefultPerms != NULL) {
  2486. StrNCpy(pszPerms, pszDefultPerms, iMaxPerms);
  2487. SysFree(pszDefultPerms);
  2488. } else
  2489. SetEmptyString(pszPerms);
  2490. }
  2491. return (0);
  2492. }
  2493. static int SMTPTryApplyLocalCMD5Auth(SMTPSession & SMTPS, char const *pszChallenge,
  2494.      char const *pszUsername, char const *pszDigest)
  2495. {
  2496. ///////////////////////////////////////////////////////////////////////////////
  2497. //  First try to lookup  mailusers.tab
  2498. ///////////////////////////////////////////////////////////////////////////////
  2499. char szAccountUser[MAX_ADDR_NAME] = "";
  2500. char szAccountDomain[MAX_HOST_NAME] = "";
  2501. if (StrSplitString(pszUsername, POP3_USER_SPLITTERS, szAccountUser, sizeof(szAccountUser),
  2502.    szAccountDomain, sizeof(szAccountDomain)) < 0)
  2503. return (ErrGetErrorCode());
  2504. UserInfo *pUI = UsrGetUserByName(szAccountDomain, szAccountUser);
  2505. if (pUI != NULL) {
  2506. ///////////////////////////////////////////////////////////////////////////////
  2507. //  Compute MD5 response ( secret , challenge , digest )
  2508. ///////////////////////////////////////////////////////////////////////////////
  2509. char szCurrDigest[512] = "";
  2510. if (MscCramMD5(pUI->pszPassword, pszChallenge, szCurrDigest) < 0) {
  2511. UsrFreeUserInfo(pUI);
  2512. return (ErrGetErrorCode());
  2513. }
  2514. if (stricmp(szCurrDigest, pszDigest) == 0) {
  2515. ///////////////////////////////////////////////////////////////////////////////
  2516. //  Apply user configuration
  2517. ///////////////////////////////////////////////////////////////////////////////
  2518. if (SMTPApplyUserConfig(SMTPS, pUI) < 0) {
  2519. ErrorPush();
  2520. UsrFreeUserInfo(pUI);
  2521. return (ErrorPop());
  2522. }
  2523. UsrFreeUserInfo(pUI);
  2524. return (0);
  2525. }
  2526. UsrFreeUserInfo(pUI);
  2527. }
  2528. ErrSetErrorCode(ERR_SMTP_AUTH_FAILED);
  2529. return (ERR_SMTP_AUTH_FAILED);
  2530. }
  2531. static int SMTPTryApplyUsrPwdAuth(SMTPSession & SMTPS, char const *pszUsername,
  2532.   char const *pszPassword)
  2533. {
  2534. char szAuthFilePath[SYS_MAX_PATH] = "";
  2535. SMTPGetAuthFilePath(szAuthFilePath, sizeof(szAuthFilePath));
  2536. char szResLock[SYS_MAX_PATH] = "";
  2537. RLCK_HANDLE hResLock = RLckLockSH(CfgGetBasedPath(szAuthFilePath, szResLock,
  2538.   sizeof(szResLock)));
  2539. if (hResLock == INVALID_RLCK_HANDLE)
  2540. return (ErrGetErrorCode());
  2541. FILE *pAuthFile = fopen(szAuthFilePath, "rt");
  2542. if (pAuthFile == NULL) {
  2543. RLckUnlockSH(hResLock);
  2544. ErrSetErrorCode(ERR_FILE_OPEN, szAuthFilePath);
  2545. return (ERR_FILE_OPEN);
  2546. }
  2547. char szAuthLine[SVR_SMTPAUTH_LINE_MAX] = "";
  2548. while (MscGetConfigLine(szAuthLine, sizeof(szAuthLine) - 1, pAuthFile) != NULL) {
  2549. char **ppszStrings = StrGetTabLineStrings(szAuthLine);
  2550. if (ppszStrings == NULL)
  2551. continue;
  2552. int iFieldsCount = StrStringsCount(ppszStrings);
  2553. if ((iFieldsCount >= smtpaMax) &&
  2554.     (strcmp(ppszStrings[smtpaUsername], pszUsername) == 0) &&
  2555.     (strcmp(ppszStrings[smtpaPassword], pszPassword) == 0)) {
  2556. ///////////////////////////////////////////////////////////////////////////////
  2557. //  Apply user perms to SMTP config
  2558. ///////////////////////////////////////////////////////////////////////////////
  2559. SMTPApplyPerms(SMTPS, ppszStrings[smtpaPerms]);
  2560. StrFreeStrings(ppszStrings);
  2561. fclose(pAuthFile);
  2562. RLckUnlockSH(hResLock);
  2563. return (0);
  2564. }
  2565. StrFreeStrings(ppszStrings);
  2566. }
  2567. fclose(pAuthFile);
  2568. RLckUnlockSH(hResLock);
  2569. ErrSetErrorCode(ERR_SMTP_AUTH_FAILED);
  2570. return (ERR_SMTP_AUTH_FAILED);
  2571. }
  2572. static int SMTPTryApplyCMD5Auth(SMTPSession & SMTPS, char const *pszChallenge,
  2573. char const *pszUsername, char const *pszDigest)
  2574. {
  2575. char szAuthFilePath[SYS_MAX_PATH] = "";
  2576. SMTPGetAuthFilePath(szAuthFilePath, sizeof(szAuthFilePath));
  2577. FILE *pAuthFile = fopen(szAuthFilePath, "rt");
  2578. if (pAuthFile == NULL) {
  2579. ErrSetErrorCode(ERR_FILE_OPEN, szAuthFilePath);
  2580. return (ERR_FILE_OPEN);
  2581. }
  2582. char szAuthLine[SVR_SMTPAUTH_LINE_MAX] = "";
  2583. while (MscGetConfigLine(szAuthLine, sizeof(szAuthLine) - 1, pAuthFile) != NULL) {
  2584. char **ppszStrings = StrGetTabLineStrings(szAuthLine);
  2585. if (ppszStrings == NULL)
  2586. continue;
  2587. int iFieldsCount = StrStringsCount(ppszStrings);
  2588. if ((iFieldsCount >= smtpaMax) &&
  2589.     (strcmp(ppszStrings[smtpaUsername], pszUsername) == 0)) {
  2590. char szCurrDigest[512] = "";
  2591. ///////////////////////////////////////////////////////////////////////////////
  2592. //  Compute MD5 response ( secret , challenge , digest )
  2593. ///////////////////////////////////////////////////////////////////////////////
  2594. if (MscCramMD5(ppszStrings[smtpaPassword], pszChallenge, szCurrDigest) <
  2595.     0) {
  2596. StrFreeStrings(ppszStrings);
  2597. fclose(pAuthFile);
  2598. return (ErrGetErrorCode());
  2599. }
  2600. if (stricmp(szCurrDigest, pszDigest) == 0) {
  2601. ///////////////////////////////////////////////////////////////////////////////
  2602. //  Apply user perms to SMTP config
  2603. ///////////////////////////////////////////////////////////////////////////////
  2604. SMTPApplyPerms(SMTPS, ppszStrings[smtpaPerms]);
  2605. StrFreeStrings(ppszStrings);
  2606. fclose(pAuthFile);
  2607. return (0);
  2608. }
  2609. }
  2610. StrFreeStrings(ppszStrings);
  2611. }
  2612. fclose(pAuthFile);
  2613. ErrSetErrorCode(ERR_SMTP_AUTH_FAILED);
  2614. return (ERR_SMTP_AUTH_FAILED);
  2615. }
  2616. static int SMTPDoAuthCramMD5(BSOCK_HANDLE hBSock, SMTPSession & SMTPS, char const *pszAuthParam)
  2617. {
  2618. ///////////////////////////////////////////////////////////////////////////////
  2619. //  Emit encoded64 challenge and get client response
  2620. ///////////////////////////////////////////////////////////////////////////////
  2621. unsigned int uEnc64Length = 0;
  2622. char szChallenge[512] = "";
  2623. encode64(SMTPS.szTimeStamp, strlen(SMTPS.szTimeStamp), szChallenge,
  2624.  sizeof(szChallenge), &uEnc64Length);
  2625. if ((BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout, "334 %s", szChallenge) < 0) ||
  2626.     (BSckGetString(hBSock, szChallenge, sizeof(szChallenge) - 1, SMTPS.pSMTPCfg->iTimeout)
  2627.      == NULL))
  2628. return (ErrGetErrorCode());
  2629. ///////////////////////////////////////////////////////////////////////////////
  2630. //  Decode ( base64 ) client response
  2631. ///////////////////////////////////////////////////////////////////////////////
  2632. unsigned int uDec64Length = 0;
  2633. char szClientResp[512] = "";
  2634. if (decode64(szChallenge, strlen(szChallenge), szClientResp, &uDec64Length) != 0) {
  2635. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2636. ErrSetErrorCode(ERR_BAD_SMTP_CMD_SYNTAX);
  2637. return (ERR_BAD_SMTP_CMD_SYNTAX);
  2638. }
  2639. ///////////////////////////////////////////////////////////////////////////////
  2640. //  Extract the username and client digest
  2641. ///////////////////////////////////////////////////////////////////////////////
  2642. char *pszUsername = szClientResp;
  2643. char *pszDigest = strchr(szClientResp, ' ');
  2644. if (pszDigest == NULL) {
  2645. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2646. ErrSetErrorCode(ERR_BAD_SMTP_CMD_SYNTAX);
  2647. return (ERR_BAD_SMTP_CMD_SYNTAX);
  2648. }
  2649. *pszDigest++ = '';
  2650. ///////////////////////////////////////////////////////////////////////////////
  2651. //  Validate client response
  2652. ///////////////////////////////////////////////////////////////////////////////
  2653. if ((SMTPTryApplyLocalCMD5Auth(SMTPS, SMTPS.szTimeStamp, pszUsername,
  2654.        pszDigest) < 0) &&
  2655.     (SMTPTryApplyCMD5Auth(SMTPS, SMTPS.szTimeStamp, pszUsername, pszDigest) < 0)) {
  2656. ErrorPush();
  2657. SMTPSendError(hBSock, SMTPS, "503 Authentication failed");
  2658. return (ErrorPop());
  2659. }
  2660. ///////////////////////////////////////////////////////////////////////////////
  2661. //  Set the logon user
  2662. ///////////////////////////////////////////////////////////////////////////////
  2663. StrSNCpy(SMTPS.szLogonUser, pszUsername);
  2664. SMTPS.ulFlags |= SMTPF_AUTHENTICATED;
  2665. SMTPS.iSMTPState = stateAuthenticated;
  2666. BSckSendString(hBSock, "235 Authentication successful", SMTPS.pSMTPCfg->iTimeout);
  2667. return (0);
  2668. }
  2669. static int SMTPHandleCmd_AUTH(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  2670. {
  2671. if (SMTPS.iSMTPState != stateHelo) {
  2672. SMTPResetSession(SMTPS);
  2673. SMTPSendError(hBSock, SMTPS, "503 Bad sequence of commands");
  2674. ErrSetErrorCode(ERR_SMTP_BAD_CMD_SEQUENCE);
  2675. return (ERR_SMTP_BAD_CMD_SEQUENCE);
  2676. }
  2677. int iTokensCount;
  2678. char **ppszTokens = StrTokenize(pszCommand, " ");
  2679. if ((ppszTokens == NULL) || ((iTokensCount = StrStringsCount(ppszTokens)) < 2)) {
  2680. if (ppszTokens != NULL)
  2681. StrFreeStrings(ppszTokens);
  2682. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2683. return (-1);
  2684. }
  2685. ///////////////////////////////////////////////////////////////////////////////
  2686. //  Decode AUTH command params
  2687. ///////////////////////////////////////////////////////////////////////////////
  2688. char szAuthType[128] = "";
  2689. char szAuthParam[PLAIN_AUTH_PARAM_SIZE] = "";
  2690. StrSNCpy(szAuthType, ppszTokens[1]);
  2691. if (iTokensCount > 2)
  2692. StrSNCpy(szAuthParam, ppszTokens[2]);
  2693. StrFreeStrings(ppszTokens);
  2694. ///////////////////////////////////////////////////////////////////////////////
  2695. //  Handle authentication methods
  2696. ///////////////////////////////////////////////////////////////////////////////
  2697. if (stricmp(szAuthType, "plain") == 0) {
  2698. if (SMTPDoAuthPlain(hBSock, SMTPS, szAuthParam) < 0) {
  2699. ErrorPush();
  2700. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  2701. SMTPLogSession(SMTPS, "", "", "AUTH=EFAIL:TYPE=PLAIN", 0);
  2702. return (ErrorPop());
  2703. }
  2704. } else if (stricmp(szAuthType, "login") == 0) {
  2705. if (SMTPDoAuthLogin(hBSock, SMTPS, szAuthParam) < 0) {
  2706. ErrorPush();
  2707. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  2708. SMTPLogSession(SMTPS, "", "", "AUTH=EFAIL:TYPE=LOGIN", 0);
  2709. return (ErrorPop());
  2710. }
  2711. } else if (stricmp(szAuthType, "cram-md5") == 0) {
  2712. if (SMTPDoAuthCramMD5(hBSock, SMTPS, szAuthParam) < 0) {
  2713. ErrorPush();
  2714. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  2715. SMTPLogSession(SMTPS, "", "", "AUTH=EFAIL:TYPE=CRAM-MD5", 0);
  2716. return (ErrorPop());
  2717. }
  2718. } else {
  2719. ///////////////////////////////////////////////////////////////////////////////
  2720. //  Handle external authentication methods
  2721. ///////////////////////////////////////////////////////////////////////////////
  2722. if (SMTPDoAuthExternal(hBSock, SMTPS, szAuthType) < 0) {
  2723. ErrorPush();
  2724. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  2725. SMTPLogSession(SMTPS, "", "", "AUTH=EFAIL:TYPE=EXTRN", 0);
  2726. return (ErrorPop());
  2727. }
  2728. }
  2729. return (0);
  2730. }
  2731. static int SMTPSendMultilineResponse(BSOCK_HANDLE hBSock, int iTimeout, FILE * pRespFile)
  2732. {
  2733. rewind(pRespFile);
  2734. char szCurrLine[1024] = "";
  2735. char szPrevLine[1024] = "";
  2736. if (MscGetString(pRespFile, szPrevLine, sizeof(szPrevLine) - 1) != NULL) {
  2737. while (MscGetString(pRespFile, szCurrLine, sizeof(szCurrLine) - 1) != NULL) {
  2738. szPrevLine[3] = '-';
  2739. if (BSckSendString(hBSock, szPrevLine, iTimeout) < 0)
  2740. return (ErrGetErrorCode());
  2741. StrSNCpy(szPrevLine, szCurrLine);
  2742. }
  2743. if (BSckSendString(hBSock, szPrevLine, iTimeout) < 0)
  2744. return (ErrGetErrorCode());
  2745. }
  2746. return (0);
  2747. }
  2748. static int SMTPHandleCmd_RSET(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  2749. {
  2750. SMTPResetSession(SMTPS);
  2751. BSckSendString(hBSock, "250 OK", SMTPS.pSMTPCfg->iTimeout);
  2752. return (0);
  2753. }
  2754. static int SMTPHandleCmd_NOOP(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  2755. {
  2756. BSckSendString(hBSock, "250 OK", SMTPS.pSMTPCfg->iTimeout);
  2757. return (0);
  2758. }
  2759. static int SMTPHandleCmd_HELP(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  2760. {
  2761. BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout,
  2762. "250-HELO EHLO MAIL RCPT DATA AUTHrn"
  2763. "250-RSET VRFY ETRN NOOP HELP QUITrn"
  2764. "250 For more information please visit : %s", APP_URL);
  2765. return (0);
  2766. }
  2767. static int SMTPHandleCmd_QUIT(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  2768. {
  2769. SMTPS.iSMTPState = stateExit;
  2770. BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout,
  2771. "221 %s service closing transmission channel", SMTP_SERVER_NAME);
  2772. return (0);
  2773. }
  2774. static int SMTPHandleCmd_VRFY(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  2775. {
  2776. ///////////////////////////////////////////////////////////////////////////////
  2777. //  Check if VRFY is enabled
  2778. ///////////////////////////////////////////////////////////////////////////////
  2779. if (((SMTPS.ulFlags & SMTPF_VRFY_ENABLED) == 0) &&
  2780.     !SvrTestConfigFlag("AllowSmtpVRFY", false, SMTPS.hSvrConfig)) {
  2781. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  2782. SMTPLogSession(SMTPS, "", "", "VRFY=EACCESS", 0);
  2783. SMTPSendError(hBSock, SMTPS, "252 Argument not checked");
  2784. return (-1);
  2785. }
  2786. char **ppszTokens = StrTokenize(pszCommand, " ");
  2787. if ((ppszTokens == NULL) || (StrStringsCount(ppszTokens) != 2)) {
  2788. if (ppszTokens != NULL)
  2789. StrFreeStrings(ppszTokens);
  2790. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2791. return (-1);
  2792. }
  2793. char szVrfyUser[MAX_ADDR_NAME] = "";
  2794. char szVrfyDomain[MAX_ADDR_NAME] = "";
  2795. if (USmtpSplitEmailAddr(ppszTokens[1], szVrfyUser, szVrfyDomain) < 0) {
  2796. ErrorPush();
  2797. StrFreeStrings(ppszTokens);
  2798. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2799. return (ErrorPop());
  2800. }
  2801. StrFreeStrings(ppszTokens);
  2802. UserInfo *pUI = UsrGetUserByNameOrAlias(szVrfyDomain, szVrfyUser);
  2803. if (pUI != NULL) {
  2804. char *pszRealName = UsrGetUserInfoVar(pUI, "RealName", "Unknown");
  2805. BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout,
  2806. "250 %s <%s@%s>", pszRealName, pUI->pszName, pUI->pszDomain);
  2807. SysFree(pszRealName);
  2808. UsrFreeUserInfo(pUI);
  2809. } else {
  2810. if (USmlIsCmdAliasAccount(szVrfyDomain, szVrfyUser) < 0) {
  2811. SMTPSendError(hBSock, SMTPS, "550 String does not match anything");
  2812. ErrSetErrorCode(ERR_USER_NOT_LOCAL);
  2813. return (ERR_USER_NOT_LOCAL);
  2814. }
  2815. BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout,
  2816. "250 Local account <%s@%s>", szVrfyUser, szVrfyDomain);
  2817. }
  2818. return (0);
  2819. }
  2820. static int SMTPHandleCmd_ETRN(const char *pszCommand, BSOCK_HANDLE hBSock, SMTPSession & SMTPS)
  2821. {
  2822. ///////////////////////////////////////////////////////////////////////////////
  2823. //  Check if ETRN is enabled
  2824. ///////////////////////////////////////////////////////////////////////////////
  2825. if (((SMTPS.ulFlags & SMTPF_ETRN_ENABLED) == 0) &&
  2826.     !SvrTestConfigFlag("AllowSmtpETRN", false, SMTPS.hSvrConfig)) {
  2827. if (SMTPLogEnabled(SMTPS.hShbSMTP, SMTPS.pSMTPCfg))
  2828. SMTPLogSession(SMTPS, "", "", "ETRN=EACCESS", 0);
  2829. SMTPSendError(hBSock, SMTPS, "501 Command not accepted");
  2830. return (-1);
  2831. }
  2832. char **ppszTokens = StrTokenize(pszCommand, " ");
  2833. if ((ppszTokens == NULL) || (StrStringsCount(ppszTokens) != 2)) {
  2834. if (ppszTokens != NULL)
  2835. StrFreeStrings(ppszTokens);
  2836. SMTPSendError(hBSock, SMTPS, "501 Syntax error in parameters or arguments");
  2837. return (-1);
  2838. }
  2839. ///////////////////////////////////////////////////////////////////////////////
  2840. //  Do a matched flush of the rsnd arena
  2841. ///////////////////////////////////////////////////////////////////////////////
  2842. if (QueFlushRsndArena(hSpoolQueue, ppszTokens[1]) < 0) {
  2843. ErrorPush();
  2844. StrFreeStrings(ppszTokens);
  2845. SMTPSendError(hBSock, SMTPS,
  2846.       "451 Requested action aborted: (%d) local error in processing",
  2847.       ErrorFetch());
  2848. return (ErrorPop());
  2849. }
  2850. BSckVSendString(hBSock, SMTPS.pSMTPCfg->iTimeout,
  2851. "250 Queueing for '%s' has been started", ppszTokens[1]);
  2852. StrFreeStrings(ppszTokens);
  2853. return (0);
  2854. }