Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7161 lines
230 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. smtpinst.cxx
  5. Abstract:
  6. This module defines the SMTP_SERVER_INSTANCE class
  7. Author:
  8. Johnson Apacible (JohnsonA) June-04-1996
  9. Revision History:
  10. David Howell (dhowell) May-1997 Added Etrn Logic
  11. Nimish Khanolkar (NimishK) Jan - 1998 - modified for CAPI store ce
  12. --*/
  13. #define INCL_INETSRV_INCS
  14. #include "smtpinc.h"
  15. #include <iis64.h>
  16. #include "iiscnfg.h"
  17. #include <mdmsg.h>
  18. #include <commsg.h>
  19. #include <imd.h>
  20. #include <mb.hxx>
  21. #include <nsepname.hxx>
  22. #include "smtpcli.hxx"
  23. #include "dirnot.hxx"
  24. #include <smtpinet.h>
  25. // SEO Header files
  26. #define _ATL_NO_DEBUG_CRT
  27. #define _ATL_STATIC_REGISTRY 1
  28. #define _ASSERTE _ASSERT
  29. #define _WINDLL
  30. #include "atlbase.h"
  31. extern CComModule _Module;
  32. #include "atlcom.h"
  33. #undef _WINDLL
  34. #include "smtpsvr.h"
  35. #include "seo.h"
  36. #include "seolib.h"
  37. #include "smtpdisp.h"
  38. #include "seodisp.h"
  39. #include "seo_i.c"
  40. #include "tran_evntlog.h"
  41. extern "C" {
  42. int strcasecmp(char *s1, char *s2);
  43. int strncasecmp(char *s1, char *s2, int n);
  44. }
  45. #define STORE_DRIVER_PROGID L"Exchange.NtfsDrv"
  46. #define SMTPSERVER_PROGID L"SMTPServer.SMTPServer.1"
  47. #if 0
  48. extern VOID
  49. ServerEventCompletion(
  50. PVOID pvContext,
  51. DWORD cbWritten,
  52. DWORD dwCompletionStatus,
  53. OVERLAPPED * lpo
  54. );
  55. #endif
  56. //extern "C++" {
  57. //BOOL g_IsShuttingDown = FALSE;
  58. //}
  59. DWORD BuildInitialQueueProc(void *lpThis);
  60. VOID ProcessInitialQueueObjects(PVOID pvContext,
  61. DWORD cbWritten,
  62. DWORD dwCompletionStatus,
  63. OVERLAPPED *lpo);
  64. DWORD EnumAllDomains(void *ptr);
  65. //
  66. // Constants
  67. //
  68. //
  69. // Globals
  70. //
  71. #define MAX_CONNECTION_OBJECTS 5000
  72. #define DEFAULT_LOGON_METHOD LOGON32_LOGON_INTERACTIVE
  73. #define DEFAULT_USE_SUBAUTH TRUE
  74. #define DEFAULT_ANONYMOUS_PWD ""
  75. PFN_SF_NOTIFY g_pSslKeysNotify = NULL;
  76. extern STORE_CHANGE_NOTIFIER *g_pCAPIStoreChangeNotifier;
  77. SmtpMappingSupportFunction(
  78. PVOID pvInstance,
  79. PVOID pData,
  80. DWORD dwPropId);
  81. SERVICE_MAPPING_CONTEXT g_SmtpSMC = { SmtpMappingSupportFunction};
  82. //
  83. // Prototypes
  84. //
  85. BOOL
  86. SetSslKeysNotify(
  87. PFN_SF_NOTIFY pFn
  88. );
  89. /************************************************************
  90. * Symbolic Constants
  91. ************************************************************/
  92. static TCHAR szServicePath[] = TEXT("System\\CurrentControlSet\\Services\\");
  93. static TCHAR szParametersKey[] = TEXT("\\Parameters");
  94. static TCHAR szParamPath[] = TEXT("System\\CurrentControlSet\\Services\\SmtpSvc\\Parameters");
  95. static WCHAR szParamPathW[] = L"System\\CurrentControlSet\\Services\\SmtpSvc\\Parameters";
  96. static TCHAR szTcpipPath[] = TEXT("System\\CurrentControlSet\\Services\\Tcpip\\Parameters");
  97. static TCHAR szTcpipTransient[] = TEXT("Transient");
  98. static TCHAR szMaxSmtpErrors[] = TEXT("MaxErrors");
  99. static WCHAR szMaxSmtpErrorsW[] = L"MaxErrors";
  100. static TCHAR szMaxRemoteTimeOut[] = TEXT("MaxRemoteTimeOut");
  101. static WCHAR szMaxRemoteTimeOutW[] = L"MaxRemoteTimeOut";
  102. static TCHAR szMaxMsgSize[] = TEXT("MaxMsgSize");
  103. static WCHAR szMaxMsgSizeW[] = L"MaxMsgSize";
  104. static TCHAR szMaxMsgSizeBeforeClose[] = TEXT("MaxMsgSizeBeforeClose");
  105. static WCHAR szMaxMsgSizeBeforeCloseW[] = L"MaxMsgSizeBeforeClose";
  106. static TCHAR szMaxRcpts[] = TEXT("MaxRcpts");
  107. static WCHAR szMaxRcptsW[] = L"MaxRcpts";
  108. static TCHAR szEnableReverseLookup[] = TEXT("EnableReverseLookup");
  109. static WCHAR szEnableReverseLookupW[] = L"EnableReverseLookup";
  110. static TCHAR szDomains[] = TEXT("Domains");
  111. static WCHAR szDomainsW[] = L"Domains";
  112. static TCHAR szNameResolution[] = TEXT("NameResolution");
  113. static WCHAR szNameResolutionW[] = L"NameResolution";
  114. static TCHAR szSmartHostType[] = TEXT("SmartHostUseType");
  115. static WCHAR szSmartHostTypeW[] = L"SmartHostUseType";
  116. static TCHAR szRetryAttempts[] = TEXT("MaxRetryAttempts");
  117. static WCHAR szRetryAttemptsW[] = L"MaxRetryAttempts";
  118. static TCHAR szRetryMinutes[] = TEXT("MaxRetryMinutes");
  119. static WCHAR szRetryMinutesW[] = L"MaxRetryMinutes";
  120. static TCHAR szShouldPipelineOut[] = TEXT("PipelineOutput");
  121. static WCHAR szShouldPipelineOutW[] = L"PipelineOutput";
  122. static TCHAR szShouldPipelineIn[] = TEXT("PipelineInput");
  123. static WCHAR szShouldPipelineInW[] = L"PipelineInput";
  124. static TCHAR szMaxHopCount[] = TEXT("MaxHopCount");
  125. static WCHAR szMaxHopCountW[] = L"MaxHopCount";
  126. static TCHAR szMaxOutConnections[] = TEXT("MaxOutConnections");
  127. static WCHAR szMaxOutConnectionsW[] = L"MaxOutConnections";
  128. static TCHAR szSendBadToAdmin[] = TEXT("SendBadToAdmin");
  129. static WCHAR szSendBadToAdminW[] = L"SendBadToAdmin";
  130. static TCHAR szSendNDRToAdmin[] = TEXT("SentNDRToAdmin");
  131. static WCHAR szSendNDRToAdminW[] = L"SentNDRToAdmin";
  132. static TCHAR szRoutingSources[] = TEXT("RoutingSources");
  133. static WCHAR szRoutingSourcesW[] = L"RoutingSources";
  134. static TCHAR szRoutingThreads[] = TEXT("RoutingThreads");
  135. static WCHAR szRoutingThreadsW[] = L"RoutingThreads";
  136. static TCHAR szDirBuffers[] = TEXT("MaxDirectoryBuffers");
  137. static WCHAR szDirBuffersW[] = L"MaxDirectoryBuffers";
  138. static TCHAR szDirBuffersSize[] = TEXT("DirectoryBuffSize");
  139. static WCHAR szDirBuffersSizeW[] = L"DirectoryBufferSize";
  140. static TCHAR szDirPendingIos[] = TEXT("NumDirPendingIos");
  141. static WCHAR szDirPendingIosW[] = L"NumDirPendingIos";
  142. static TCHAR szBadMailDir[] = TEXT("BadMailDir");
  143. static WCHAR szBadMailDirW[] = L"BadMailDir";
  144. static TCHAR szMailQueueDir[] = TEXT("MailQueueDir");
  145. static WCHAR szMailQueueDirW[] = L"MailQueueDir";
  146. static TCHAR szShouldDeliver[] = TEXT("ShouldDeliver");
  147. static WCHAR szShouldDeliverW[] = L"ShouldDeliver";
  148. static TCHAR szShouldDelete[] = TEXT("ShouldDelete");
  149. static WCHAR szShouldDeleteW[] = L"ShouldDelete";
  150. static TCHAR szDeleteDir[] = TEXT("DeleteDir");
  151. static WCHAR szDeleteDirW[] = L"DeleteDir";
  152. static TCHAR szMaxAddrObjects[] = TEXT("MaxAddressObjects");
  153. static WCHAR szMaxAddrObjectsW[] = L"MaxAddressObjects";
  154. static TCHAR szMaxMailObjects[] = TEXT("MaxMailObjects");
  155. static WCHAR szMaxMailObjectsW[] = L"MaxMailObjects";
  156. static TCHAR szRoutingDll[] = TEXT("RoutingDll");
  157. static WCHAR szRoutingDllW[] = L"RoutingDll";
  158. static TCHAR szUseFileLinks[] = TEXT("UseFileLinks");
  159. static WCHAR szUseFileLinksW[] = L"UseFileLinks";
  160. static TCHAR szMsgBatchLimit[] = TEXT("BatchMsgLimit");
  161. static WCHAR szMsgBatchLimitW[] = L"BatchMsgLimit";
  162. static TCHAR szMailPickupDir[] = TEXT("MailPickupDir");
  163. static WCHAR szMailPickupDirW[] = L"MailPickupDir";
  164. static TCHAR szMailDropDir[] = TEXT("MailDropDir");
  165. static WCHAR szMailDropDirW[] = L"MailDropDir";
  166. static TCHAR szShouldPickupMail[] = TEXT("ShouldPickupMail");
  167. static WCHAR szShouldPickupMailW[] = L"ShouldPickupMail";
  168. static TCHAR szCommandLogMask[] = TEXT("CommandLogMask");
  169. static WCHAR szCommandLogMaskW[] = L"CommandLogMask";
  170. static TCHAR szShowEightBitMime[] = TEXT("ShowEightBitMime");
  171. static WCHAR szShowEightBitMimeW[] = L"ShowEightBitMime";
  172. static TCHAR szShowBinaryMime[] = TEXT("ShowBinaryMime");
  173. static WCHAR szShowBinaryMimeW[] = L"ShowBinaryMime";
  174. static TCHAR szShowChunking[] = TEXT("ShowChunking");
  175. static WCHAR szShowChunkingW[] = L"ShowChunking";
  176. static TCHAR szFlushMailFiles[] = TEXT("FlushMailFiles");
  177. static WCHAR szFlushMailFilesW[] = L"FlushMailFiles";
  178. static TCHAR szVirtualRoot[] = TEXT("Virtual Roots");
  179. static WCHAR szVirtualRootW[] = L"Virtual Roots";
  180. static TCHAR szRRetryAttempts[] = TEXT("MaxRemoteRetryAttempts");
  181. static WCHAR szRRetryAttemptsW[] = L"MaxRemoteRetryAttempts";
  182. static TCHAR szRRetryMinutes[] = TEXT("MaxRemoteRetryMinutes");
  183. static WCHAR szRRetryMinutesW[] = L"MaxRemoteRetryMinutes";
  184. static TCHAR szShareRetryMinutes[] = TEXT("MaxShareRetryMinutes");
  185. static WCHAR szShareRetryMinutesW[] = L"MaxShareRetryMinutes";
  186. // Always use ANSI for Internet compatibility, even if UNICODE is defined
  187. static WCHAR szDefaultDomainW[] = L"DefaultDomain";
  188. static TCHAR szDefaultDomain[] = TEXT("DefaultDomain");
  189. static WCHAR szConnectResponseW[] = L"ConnectResponse";
  190. static TCHAR szConnectResponse[] = TEXT("ConnectResponse");
  191. static WCHAR szSmartHostNameW[] = L"SmartHost";
  192. static TCHAR szSmartHostName[] = TEXT("SmartHost");
  193. //
  194. // Added by keithlau on 7/12/96
  195. //
  196. #define SMTP_EVENTLOG_MAX_ITEMS 10
  197. #define SMTP_INIT_ABSORT 0x00000001
  198. #define SMTP_INIT_CSLOCK 0x00000002
  199. #define SMTP_INIT_OUTLOCK 0x00000004
  200. #define SMTP_INIT_GENLOCK 0x00000008
  201. const LPSTR pszPackagesDefault = "NTLM\0GSSAPI\0";
  202. const DWORD ccbPackagesDefault = sizeof( "NTLM\0GSSAPI\0" );
  203. extern AQ_INITIALIZE_EX_FUNCTION g_pfnInitializeAQ;
  204. extern AQ_DEINITIALIZE_EX_FUNCTION g_pfnDeinitializeAQ;
  205. extern HRESULT CallInstanceInitStoreDriver(DWORD InstanceId, IAdvQueue *pIAq, char * UserName,
  206. char * DomainName, char * Password, char * DnToUse);
  207. extern void CallInstanceDeInitStoreDriver(DWORD InstanceId);
  208. //extern HRESULT HrGetGatewayDN(IN OUT DWORD *pcbBuffer,
  209. // IN LPSTR szBuffer);
  210. inline BOOL
  211. ConvertToMultisz(LPSTR szMulti, DWORD *pdwCount, LPSTR szAuthPack)
  212. {
  213. CHAR *pcStart = szAuthPack, *pc;
  214. DWORD dw = 0;
  215. pc = pcStart;
  216. if (*pc == '\0' || *pc == ',')
  217. return FALSE;
  218. *pdwCount = 0;
  219. while (TRUE) {
  220. if (*pc == '\0') {
  221. strcpy(&szMulti[dw], pcStart);
  222. (*pdwCount)++;
  223. dw += lstrlen(pcStart);
  224. szMulti[dw + 1] = '\0';
  225. return TRUE;
  226. } else if (*pc == ',') {
  227. *pc = '\0';
  228. lstrcpy(&szMulti[dw], pcStart);
  229. (*pdwCount)++;
  230. dw += lstrlen(pcStart);
  231. dw++;
  232. *pc = ',';
  233. pcStart = ++pc;
  234. } else {
  235. pc++;
  236. }
  237. }
  238. }
  239. //
  240. // Quick and dirty range check using inlines (KeithLau 7/28/96)
  241. //
  242. static inline BOOL pValidateRange(DWORD dwValue, DWORD dwLower, DWORD dwUpper)
  243. {
  244. // Inclusive
  245. if ((dwValue >= dwLower) && (dwValue <= dwUpper))
  246. return (TRUE);
  247. SetLastError(ERROR_INVALID_PARAMETER);
  248. return (FALSE);
  249. }
  250. //
  251. // Quick and dirty string validation
  252. //
  253. static inline BOOL pValidateStringPtr(LPWSTR lpwszString, DWORD dwMaxLength)
  254. {
  255. if (IsBadStringPtr((LPCTSTR)lpwszString, dwMaxLength))
  256. return (FALSE);
  257. while (dwMaxLength--)
  258. if (*lpwszString++ == 0)
  259. return (TRUE);
  260. return (FALSE);
  261. }
  262. static inline BOOL ConvertFromUnicode(LPWSTR pwsz, char * psz, DWORD cchMax)
  263. /*++
  264. Converts a given string into unicode string
  265. Returns FALSE on failure. Use GetLastError() for details.
  266. --*/
  267. {
  268. DWORD cch;
  269. cch = lstrlenW(pwsz) + 1;
  270. if (cchMax < cch) {
  271. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  272. return FALSE;
  273. }
  274. int iRet;
  275. iRet = WideCharToMultiByte(CP_ACP, 0, pwsz, cch, psz, cchMax, NULL, NULL);
  276. return (iRet != 0);
  277. } // ConvertToUnicode()
  278. //
  279. // Enumeration stuff
  280. //
  281. DWORD WINAPI EnumBuildQProc(LPVOID pvContext)
  282. {
  283. SMTP_SERVER_INSTANCE *pInst = (SMTP_SERVER_INSTANCE *)pvContext;
  284. _ASSERT(pInst);
  285. pInst->TriggerStoreServerEvent(SMTP_STOREDRV_ENUMMESS_EVENT);
  286. return (NO_ERROR);
  287. }
  288. DWORD
  289. InitializeInstances(
  290. PSMTP_IIS_SERVICE pService
  291. )
  292. /*++
  293. Routine Description:
  294. Reads the instances from the metabase
  295. Arguments:
  296. pService - Server instances added to.
  297. Return Value:
  298. Win32
  299. --*/
  300. {
  301. DWORD i;
  302. DWORD cInstances = 0;
  303. MB mb( (IMDCOM*) pService->QueryMDObject() );
  304. CHAR szKeyName[MAX_PATH+1];
  305. DWORD err = NO_ERROR;
  306. BUFFER buff;
  307. BOOL fMigrateRoots = FALSE;
  308. //
  309. // Open the metabase for write to get an atomic snapshot
  310. //
  311. ReOpen:
  312. if ( !mb.Open( "/LM/SMTPSVC/",
  313. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE )) {
  314. DBGPRINTF(( DBG_CONTEXT,
  315. "InitializeInstances: Cannot open path %s, error %lu\n",
  316. "/LM/SMTPSVC/", GetLastError() ));
  317. //
  318. // If the web service key isn't here, just create it
  319. //
  320. if ( !mb.Open(METADATA_MASTER_ROOT_HANDLE,
  321. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ) ||
  322. !mb.AddObject( "/LM/SMTPSVC/" )) {
  323. err = GetLastError();
  324. return err;
  325. }
  326. DBGPRINTF(( DBG_CONTEXT,
  327. "/LM/SMTPSvc not found, auto-created\n" ));
  328. mb.Close();
  329. goto ReOpen;
  330. }
  331. //_VERIFY(mb.SetString("", MD_NTAUTHENTICATION_PROVIDERS, IIS_MD_UT_SERVER, "NTLM,LOGIN"));
  332. DWORD dwVersion;
  333. if (!mb.GetDword("", MD_SMTP_SERVICE_VERSION, IIS_MD_UT_SERVER, &dwVersion)) {
  334. _VERIFY(mb.SetDword("", MD_SMTP_SERVICE_VERSION, IIS_MD_UT_SERVER, g_ProductType));
  335. }
  336. //_VERIFY(mb.SetDword("", MD_SMTP_AUTHORIZATION, IIS_MD_UT_SERVER, 7));
  337. //_VERIFY(mb.SetDword("", MD_AUTHORIZATION, IIS_MD_UT_SERVER, 7));
  338. //
  339. // Loop through instance keys and build a list. We don't keep the
  340. // metabase open because the instance instantiation code will need
  341. // to write to the metabase
  342. //
  343. TryAgain:
  344. i = 0;
  345. while ( mb.EnumObjects( "",
  346. szKeyName,
  347. i++ )) {
  348. DWORD dwInstance;
  349. //
  350. // Get the instance id
  351. //
  352. DBGPRINTF((DBG_CONTEXT,"instance key %s\n",szKeyName));
  353. dwInstance = atoi( szKeyName );
  354. if ( dwInstance == 0 ) {
  355. continue;
  356. }
  357. if ( buff.QuerySize() < (cInstances + 1) * sizeof(DWORD) ) {
  358. if ( !buff.Resize( (cInstances + 10) * sizeof(DWORD)) ) {
  359. return GetLastError();
  360. }
  361. }
  362. ((DWORD *) buff.QueryPtr())[cInstances++] = dwInstance;
  363. }
  364. if ( cInstances == 0 ) {
  365. DBGPRINTF(( DBG_CONTEXT,
  366. "No defined instances\n" ));
  367. if ( !mb.AddObject( "1" )) {
  368. DBGPRINTF(( DBG_CONTEXT,
  369. "Unable to create first instance, error %d\n",
  370. GetLastError() ));
  371. return GetLastError();
  372. }
  373. fMigrateRoots = TRUE; // Force reg->metabase migration of virtual directories
  374. goto TryAgain;
  375. }
  376. DBG_REQUIRE( mb.Close() );
  377. mb.Save();
  378. for ( i = 0; i < cInstances; i++ ) {
  379. DWORD dwInstance = ((DWORD *)buff.QueryPtr())[i];
  380. if ( !g_pInetSvc->AddInstanceInfo( dwInstance, fMigrateRoots ) ) {
  381. err = GetLastError();
  382. DBGPRINTF((DBG_CONTEXT,
  383. "InitializeInstances: cannot create instance %lu, error %lu\n",
  384. dwInstance, err));
  385. //break;
  386. }
  387. }
  388. return err;
  389. } // InitializeInstances
  390. //+---------------------------------------------------------------
  391. //
  392. // Function: StopInstance
  393. //
  394. // Synopsis: Callback from IIS_SERVICE iterator
  395. //
  396. // Arguments: void
  397. //
  398. // Returns: TRUE is success, else FALSE
  399. //
  400. // History: HowardCu Created 23 May 1995
  401. //
  402. //----------------------------------------------------------------
  403. BOOL
  404. StopSmtpInstances(
  405. PVOID pvContext,
  406. PVOID pvContext1,
  407. PIIS_SERVER_INSTANCE pInstance
  408. )
  409. {
  410. PSMTP_SERVER_INSTANCE pSmtpInstance = (PSMTP_SERVER_INSTANCE)pInstance;
  411. if ( !pSmtpInstance->Stop() ) {
  412. }
  413. return TRUE;
  414. }
  415. /*++
  416. Routine Description:
  417. Shutdown each instance and terminate all global cpools
  418. Arguments:
  419. pService - Server instances added to.
  420. Return Value:
  421. Win32
  422. --*/
  423. VOID
  424. TerminateInstances( PSMTP_IIS_SERVICE pService)
  425. {
  426. PFN_INSTANCE_ENUM pfnInstanceEnum = NULL;
  427. TraceFunctEnter("TerminateInstances");
  428. //
  429. // Iterate over all instances
  430. // StopInstance callback calls SMTP_SERVER_INSTANCE::Stop()
  431. //
  432. pfnInstanceEnum = (PFN_INSTANCE_ENUM)&StopSmtpInstances;
  433. if ( !pService->EnumServiceInstances(
  434. NULL,
  435. NULL,
  436. pfnInstanceEnum
  437. ) ) {
  438. ErrorTrace(0,"Error enumerating instances");
  439. }
  440. TraceFunctLeave();
  441. }
  442. SMTP_SERVER_INSTANCE::SMTP_SERVER_INSTANCE(
  443. IN PSMTP_IIS_SERVICE pService,
  444. IN DWORD dwInstanceId,
  445. IN USHORT Port,
  446. IN LPCSTR lpszRegParamKey,
  447. IN LPWSTR lpwszAnonPasswordSecretName,
  448. IN LPWSTR lpwszVirtualRootsSecretName,
  449. IN BOOL fMigrateRoots
  450. )
  451. : IIS_SERVER_INSTANCE(pService,
  452. dwInstanceId,
  453. Port,
  454. lpszRegParamKey,
  455. lpwszAnonPasswordSecretName,
  456. lpwszVirtualRootsSecretName,
  457. fMigrateRoots)
  458. //m_signature (SMTP_SERVER_INSTANCE_SIGNATURE)
  459. {
  460. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE" );
  461. m_pSmtpStats = NULL;
  462. m_IsShuttingDown = FALSE;
  463. m_QIsShuttingDown = FALSE;
  464. m_RetryQIsShuttingDown = FALSE;
  465. m_IsFileSystemNtfs = TRUE;
  466. m_fShouldStartAcceptingConnections = TRUE;
  467. m_SmtpInitializeStatus = 0;
  468. m_cCurrentConnections = 0;
  469. m_cMaxCurrentConnections = 0;
  470. m_cCurrentOutConnections = 0;
  471. m_dwNextInboundClientId = 1;
  472. m_dwNextOutboundClientId = 1;
  473. m_dwStopHint = 2;
  474. m_cProcessClientThreads = 0;
  475. m_cNumConnInObjsAlloced = 0;
  476. m_cNumConnOutObjsAlloced = 0;
  477. m_cNumCBufferObjsAlloced = 0;
  478. m_cNumAsyncObjsAlloced = 0;
  479. m_cNumAsyncDnsObjsAlloced = 0;
  480. m_cchConnectResponse = 0;
  481. m_cCurrentRoutingThreads = 0;
  482. m_cMaxOutConnectionsPerDomain = 0;
  483. m_cMaxOutConnections = 0;
  484. m_cMaxHopCount = 0;
  485. m_RemoteSmtpPort = 0;
  486. m_cMaxRcpts = 0;
  487. m_fMasquerade = FALSE;
  488. m_fIgnoreTime = FALSE;
  489. m_fStartRetry = FALSE;
  490. m_fRequiresSSL = FALSE;
  491. m_fRequires128Bits = FALSE;
  492. m_fRequiresCertVerifySubject= FALSE;
  493. m_fRequiresCertVerifyIssuer = FALSE;
  494. m_pSSLInfo = NULL;
  495. m_fLimitRemoteConnections = TRUE;
  496. m_RDNSOptions = 0;
  497. m_fAllowVerify = FALSE;
  498. m_InstBooted = FALSE;
  499. m_fStoreDrvStartEventCalled = FALSE;
  500. m_fStoreDrvPrepShutDownEventCalled = FALSE;
  501. m_fScheduledConnection = FALSE;
  502. m_fIsRoutingTable = TRUE;
  503. m_fHaveRegisteredPrincipalNames = FALSE;
  504. m_fHelloNoValidate = FALSE;
  505. m_fMailNoValidate = FALSE;
  506. m_fRcptNoValidate = FALSE;
  507. m_fEtrnNoValidate = FALSE;
  508. m_fPickupNoValidate = FALSE;
  509. m_ProviderPackages = NULL;
  510. fInitializedAQ = FALSE;
  511. fInitializedStoreDriver = FALSE;
  512. // Raid 174038
  513. m_fDisablePickupDotStuff = FALSE;
  514. m_szMasqueradeName [0] = '\0';
  515. m_szMailQueueDir[0] = '\0';
  516. m_szMailPickupDir[0] = '\0';
  517. m_szMailDropDir[0] = '\0';
  518. m_szBadMailDir[0] = '\0';
  519. m_szMyDomain[0] = '\0';
  520. m_szDefaultDomain[0] = '\0';
  521. m_szFQDomainName[0] = '\0';
  522. m_szSmartHostName[0] = '\0';
  523. m_AdminName[0] = '\0';
  524. m_BadMailName[0] = '\0';
  525. m_DefaultRemoteUserName[0] = '\0';
  526. m_DefaultRemotePassword[0] = '\0';
  527. SmtpDir = NULL;
  528. DirPickupThreadHandle = NULL;
  529. StopHandle = NULL;
  530. m_hEnumDomainThreadHandle = NULL;
  531. m_pChangeObject = NULL;
  532. m_IAQ = NULL;
  533. m_ICM = NULL;
  534. m_pvAQInstanceContext = NULL;
  535. m_pIAdvQueueConfig = NULL;
  536. m_RemoteQ = NULL;
  537. m_ComSmtpServer = NULL;
  538. m_pSmtpInfo = NULL;
  539. m_dwEventlogLevel = LOGEVENT_LEVEL_MEDIUM;
  540. m_dwDnsFlags = 0;
  541. InitializeCriticalSection( &m_critBoot ) ;
  542. m_fInitAsyncCS = FALSE;
  543. m_signature = SMTP_INSTANCE_SIGNATURE;
  544. TraceFunctLeaveEx((LPARAM)this);
  545. return;
  546. } // SMTP_SERVER_INSTANCE::SMTP_SERVER_INSTANCE
  547. SMTP_SERVER_INSTANCE::~SMTP_SERVER_INSTANCE(
  548. VOID
  549. )
  550. {
  551. TraceFunctEnterEx((LPARAM)this, "~SMTP_SERVER_INSTANCE" );
  552. EnterCriticalSection( &m_critBoot );
  553. if ( m_InstBooted && !m_fShutdownCalled) {
  554. InitiateShutDown();
  555. } else
  556. ErrorTrace((LPARAM) this, "Shutdown for instance %d was already called", QueryInstanceId());
  557. LeaveCriticalSection( &m_critBoot );
  558. DeleteCriticalSection( &m_critBoot ) ;
  559. TraceFunctLeaveEx((LPARAM) this);
  560. }
  561. //---------------------------------------------------------------------------------------
  562. // Description:
  563. // Called by InitiateStartup() to initialize members of SMTP_SERVER_INSTANCE when
  564. // a VSI is started up. InitiateStartup() is called by IIS to start a VSI.
  565. // Arguments:
  566. // None.
  567. // Returns:
  568. // None.
  569. //---------------------------------------------------------------------------------------
  570. void SMTP_SERVER_INSTANCE::InitializeClassVariables(void)
  571. {
  572. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE:InitializeClassVariables" );
  573. m_pSmtpStats = NULL;
  574. m_IsShuttingDown = FALSE;
  575. m_QIsShuttingDown = FALSE;
  576. m_RetryQIsShuttingDown = FALSE;
  577. m_fShouldStartAcceptingConnections = TRUE;
  578. m_SmtpInitializeStatus = 0;
  579. m_cCurrentConnections = 0;
  580. m_cMaxCurrentConnections = 0;
  581. m_cCurrentOutConnections = 0;
  582. m_dwNextInboundClientId = 1;
  583. m_dwNextOutboundClientId = 1;
  584. m_dwStopHint = 2;
  585. m_cProcessClientThreads = 0;
  586. m_cNumConnInObjsAlloced = 0;
  587. m_cNumConnOutObjsAlloced = 0;
  588. m_cNumCBufferObjsAlloced = 0;
  589. m_cNumAsyncObjsAlloced = 0;
  590. m_cNumAsyncDnsObjsAlloced = 0;
  591. m_cchConnectResponse = 0;
  592. m_fMasquerade = FALSE;
  593. m_fIgnoreTime = FALSE;
  594. m_fStartRetry = FALSE;
  595. m_fLimitRemoteConnections = TRUE;
  596. m_fShutdownCalled = FALSE;
  597. m_fSendNDRToAdmin = FALSE;
  598. m_fSendBadToAdmin = FALSE;
  599. m_fRequiresSASL = FALSE;
  600. m_szDefaultLogonDomain[0] = '\0';
  601. m_fStoreDrvStartEventCalled = FALSE;
  602. m_fStoreDrvPrepShutDownEventCalled = FALSE;
  603. //directory pickup stuff
  604. SmtpDir = NULL;
  605. DirPickupThreadHandle = NULL;
  606. StopHandle = NULL;
  607. m_hEnumDomainThreadHandle = NULL;
  608. // Raid 174038
  609. m_fDisablePickupDotStuff = FALSE;
  610. m_QStopEvent = NULL;
  611. m_hEnumBuildQ = NULL;
  612. InitializeListHead( &m_ConnectionsList);
  613. InitializeListHead( &m_OutConnectionsList);
  614. InitializeListHead( &m_leVRoots);
  615. InitializeListHead( &m_AsynConnectList);
  616. InitializeListHead( &m_AsyncDnsList);
  617. InitializeCriticalSection( &m_csLock);
  618. m_SmtpInitializeStatus |= SMTP_INIT_CSLOCK;
  619. _ASSERT(!m_fInitAsyncCS && "Doubly initialized critsec");
  620. if(!m_fInitAsyncCS) {
  621. InitializeCriticalSection( &m_csAsyncDns );
  622. InitializeCriticalSection( &m_csAsyncConnect ) ;
  623. m_fInitAsyncCS = TRUE;
  624. }
  625. m_szConnectResponse[0] = '\0';
  626. // Set the logging handle
  627. m_InstancePropertyBag.SetLogging(&m_Logging);
  628. TraceFunctLeaveEx((LPARAM) this);
  629. }
  630. BOOL SMTP_SERVER_INSTANCE::AllocNewMessage(SMTP_ALLOC_PARAMS * Params)
  631. {
  632. TraceFunctEnterEx((LPARAM)this, "AllocNewMessage");
  633. HRESULT hr = S_OK;
  634. BOOL fRet = TRUE;
  635. Params->m_InstanceId = QueryInstanceId();
  636. Params->m_EventSmtpServer = (PVOID *) m_ComSmtpServer;
  637. Params->m_pNotify = NULL;
  638. hr = TriggerServerEvent(SMTP_STOREDRV_ALLOC_EVENT, (PVOID) Params);
  639. if (FAILED(hr)) {
  640. fRet = FALSE;
  641. }
  642. TraceFunctLeaveEx((LPARAM)this);
  643. return fRet;
  644. }
  645. HRESULT SMTP_SERVER_INSTANCE::SinkReadMetabaseDword(DWORD MetabaseId, DWORD * dwValue)
  646. {
  647. DWORD tmp = 0;
  648. HRESULT hr = S_FALSE;
  649. MB mb( (IMDCOM*)g_pInetSvc->QueryMDObject() );
  650. if (mb.Open(QueryMDPath())) {
  651. if ( dwValue && mb.GetDword("", MetabaseId, IIS_MD_UT_SERVER, &tmp)) {
  652. *dwValue = tmp;
  653. hr = S_OK;
  654. }
  655. }
  656. return hr;
  657. }
  658. HRESULT SMTP_SERVER_INSTANCE::SinkReadMetabaseString(DWORD MetabaseId, char * Buffer, DWORD * BufferSize, BOOL fSecure)
  659. {
  660. STR TempString;
  661. HRESULT hr = S_OK;
  662. MB mb( (IMDCOM*)g_pInetSvc->QueryMDObject() );
  663. DWORD MetaOptions = METADATA_INHERIT;
  664. TempString.Reset();
  665. if (fSecure) {
  666. MetaOptions |= METADATA_SECURE;
  667. }
  668. if (mb.Open(QueryMDPath())) {
  669. if (!mb.GetStr("", MetabaseId, IIS_MD_UT_SERVER, &TempString, MetaOptions) ||
  670. TempString.IsEmpty()) {
  671. hr = S_FALSE;
  672. } else {
  673. lstrcpyn(Buffer,TempString.QueryStr(), MAX_PATH);
  674. }
  675. }
  676. return hr;
  677. }
  678. //---[ SMTP_SERVER_INSTANCE::SinkReadMetabaseData -----------------------------
  679. //
  680. //
  681. // Description:
  682. // Reads arbitraty binary Metabase data (like an ACL)
  683. // Parameters:
  684. // IN MetabaseId ID to read data from
  685. // IN OUT pBuffer Buffer to read data into
  686. // IN OUT pcbBufferSize Size of buffer/valid data in buffer
  687. // Returns:
  688. // S_OK on success
  689. // HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) if buffer size is not
  690. // not large enough for requested data.
  691. // History:
  692. // 6/7/99 - MikeSwa Created
  693. //
  694. //-----------------------------------------------------------------------------
  695. HRESULT SMTP_SERVER_INSTANCE::SinkReadMetabaseData(DWORD MetabaseId,
  696. BYTE *pBuffer,
  697. DWORD *pcbBufferSize)
  698. {
  699. HRESULT hr = S_OK;
  700. MB mb( (IMDCOM*)g_pInetSvc->QueryMDObject() );
  701. if (!pcbBufferSize)
  702. return E_INVALIDARG;
  703. if (mb.Open(QueryMDPath())) {
  704. if (!mb.GetData("",
  705. MetabaseId,
  706. IIS_MD_UT_SERVER,
  707. BINARY_METADATA,
  708. pBuffer,
  709. pcbBufferSize,
  710. METADATA_INHERIT)) {
  711. hr = HRESULT_FROM_WIN32(GetLastError());
  712. }
  713. } else {
  714. hr = HRESULT_FROM_WIN32(GetLastError());
  715. }
  716. return hr;
  717. }
  718. HRESULT SMTP_SERVER_INSTANCE::TriggerLocalDelivery(IMailMsgProperties *pMsg, DWORD dwRecipientCount, DWORD * pdwRecipIndexes, IMailMsgNotify *pNotify)
  719. {
  720. HRESULT hr = S_FALSE;
  721. SMTP_ALLOC_PARAMS AllocParams;
  722. AllocParams.IMsgPtr = (PVOID) pMsg;
  723. AllocParams.m_InstanceId = QueryInstanceId();
  724. AllocParams.m_RecipientCount = dwRecipientCount;
  725. AllocParams.pdwRecipIndexes = pdwRecipIndexes;
  726. AllocParams.m_EventSmtpServer = (PVOID *) m_ComSmtpServer;
  727. AllocParams.hr = S_OK;
  728. AllocParams.m_pNotify = (PVOID) pNotify;
  729. _ASSERT(pMsg != NULL);
  730. _ASSERT(pdwRecipIndexes != NULL);
  731. _ASSERT(dwRecipientCount != 0);
  732. ADD_COUNTER (this, NumRcptsRecvdLocal, dwRecipientCount);
  733. ADD_COUNTER (this, NumRcptsRecvd, dwRecipientCount);
  734. hr = TriggerServerEvent(SMTP_STOREDRV_DELIVERY_EVENT, (PVOID) &AllocParams);
  735. //
  736. // jstamerj 1998/08/04 17:45:15:
  737. // If a sink returned a special error, return that to the caller of TriggerLocalDelivery
  738. //
  739. if (SUCCEEDED(hr) && FAILED(AllocParams.hr))
  740. hr = AllocParams.hr;
  741. return hr;
  742. }
  743. HRESULT SMTP_SERVER_INSTANCE::TriggerDirectoryDrop(IMailMsgProperties *pMsg, DWORD dwRecipientCount, DWORD * pdwRecipIndexes,
  744. LPCSTR DropDirectory)
  745. {
  746. HRESULT hr = S_FALSE;
  747. SMTP_ALLOC_PARAMS AllocParams;
  748. AllocParams.IMsgPtr = (PVOID) pMsg;
  749. AllocParams.m_InstanceId = QueryInstanceId();
  750. AllocParams.m_RecipientCount = dwRecipientCount;
  751. AllocParams.pdwRecipIndexes = pdwRecipIndexes;
  752. AllocParams.m_EventSmtpServer = (PVOID *) m_ComSmtpServer;
  753. AllocParams.m_DropDirectory = DropDirectory;
  754. AllocParams.m_pNotify = NULL;
  755. _ASSERT(pMsg != NULL);
  756. _ASSERT(pdwRecipIndexes != NULL);
  757. _ASSERT(DropDirectory != NULL);
  758. _ASSERT(dwRecipientCount != 0);
  759. if (DropDirectory != NULL) {
  760. // hr = TriggerServerEvent(SMTP_MAIL_DROP_EVENT, (PVOID) &AllocParams);
  761. } else {
  762. hr = S_FALSE;
  763. }
  764. return hr;
  765. }
  766. HRESULT SMTP_SERVER_INSTANCE::TriggerStoreServerEvent(DWORD EventType)
  767. {
  768. HRESULT hr = S_FALSE;
  769. SMTP_ALLOC_PARAMS AllocParams;
  770. AllocParams.m_InstanceId = QueryInstanceId();
  771. AllocParams.m_EventSmtpServer = (PVOID *) m_ComSmtpServer;
  772. AllocParams.m_dwStartupType = SMTP_INIT_VSERVER_STARTUP;
  773. AllocParams.m_pNotify = NULL;
  774. hr = TriggerServerEvent(EventType, (PVOID) &AllocParams);
  775. return hr;
  776. }
  777. /////////////////////////////////////////////////////////////////
  778. HRESULT SMTP_SERVER_INSTANCE::TriggerDnsResolverEvent(
  779. LPSTR HostName,
  780. LPSTR pszFQDN,
  781. DWORD dwVirtualServerId,
  782. IDnsResolverRecord **ppIDnsResolverRecord )
  783. {
  784. HRESULT hr = S_FALSE;
  785. EVENTPARAMS_DNSRESOLVERRECORD params;
  786. params.pszHostName = HostName;
  787. params.pszFQDN = pszFQDN;
  788. params.dwVirtualServerId = dwVirtualServerId;
  789. params.ppIDnsResolverRecord = ppIDnsResolverRecord;
  790. hr = TriggerServerEvent( SMTP_DNSRESOLVERRECORDSINK_EVENT, (PVOID) &params);
  791. return hr;
  792. }
  793. /////////////////////////////////////////////////////////////////
  794. HRESULT SMTP_SERVER_INSTANCE::TriggerMaxMsgSizeEvent(
  795. IUnknown *pIUnknown,
  796. IMailMsgProperties *pIMailMsg,
  797. BOOL *pfShouldImposeLimit )
  798. {
  799. HRESULT hr = S_FALSE;
  800. EVENTPARAMS_MAXMSGSIZE params;
  801. params.pIUnknown = pIUnknown;
  802. params.pIMailMsg = pIMailMsg;
  803. params.pfShouldImposeLimit = pfShouldImposeLimit;
  804. hr = TriggerServerEvent( SMTP_MAXMSGSIZE_EVENT, (PVOID)&params );
  805. return( hr );
  806. }
  807. /////////////////////////////////////////////////////////////////
  808. void SMTP_SERVER_INSTANCE::WriteLog(
  809. LPMSG_TRACK_INFO pMsgTrackInfo,
  810. IMailMsgProperties *pMsgProps,
  811. LPEVENT_LOG_INFO pEventLogInfo,
  812. LPSTR pszProtocolLog )
  813. {
  814. //
  815. // do the message tracking stuff
  816. //
  817. if( pMsgTrackInfo || pMsgProps )
  818. {
  819. EVENTPARAMS_MSGTRACKLOG msgTrackLogParams;
  820. msgTrackLogParams.pIServer = GetInstancePropertyBag();
  821. msgTrackLogParams.pIMailMsgProperties = pMsgProps;
  822. msgTrackLogParams.pMsgTrackInfo = pMsgTrackInfo;
  823. TriggerServerEvent( SMTP_MSGTRACKLOG_EVENT, (PVOID)&msgTrackLogParams );
  824. }
  825. //
  826. // do the event log stuff
  827. //
  828. if( pEventLogInfo )
  829. {
  830. SmtpLogEventEx( pEventLogInfo->dwEventId, pEventLogInfo->pszEventLogMsg, pEventLogInfo->dwErrorCode );
  831. }
  832. //
  833. // do protocol logging stuff
  834. //
  835. if( pszProtocolLog )
  836. {
  837. INETLOG_INFORMATION translog;
  838. ZeroMemory( &translog, sizeof( translog ) );
  839. translog.pszOperation = "SMTPSVC_LOG";
  840. translog.cbOperation = strlen ("SMTPSVC_LOG");
  841. translog.pszHTTPHeader = pszProtocolLog;
  842. translog.cbHTTPHeaderSize = strlen( pszProtocolLog );
  843. m_Logging.LogInformation( &translog );
  844. }
  845. }
  846. /////////////////////////////////////////////////////////////////
  847. HRESULT SMTP_SERVER_INSTANCE::TriggerLogEvent(
  848. IN DWORD idMessage,
  849. IN WORD idCategory,
  850. IN WORD cSubstrings,
  851. IN LPCSTR *rgszSubstrings,
  852. IN WORD wType,
  853. IN DWORD errCode,
  854. IN WORD iDebugLevel,
  855. IN LPCSTR szKey,
  856. IN DWORD dwOptions,
  857. IN DWORD iMessageString,
  858. IN HMODULE hModule)
  859. {
  860. HRESULT hr = S_OK;
  861. EVENTPARAMS_LOG LogParms;
  862. SMTP_LOG_EVENT_INFO LogEventInfo;
  863. // Construct the log event info
  864. LogEventInfo.idMessage = idMessage;
  865. LogEventInfo.idCategory = idCategory;
  866. LogEventInfo.cSubstrings = cSubstrings;
  867. LogEventInfo.rgszSubstrings = rgszSubstrings;
  868. LogEventInfo.wType = wType;
  869. LogEventInfo.errCode = errCode;
  870. LogEventInfo.iDebugLevel = iDebugLevel;
  871. LogEventInfo.szKey = szKey;
  872. LogEventInfo.dwOptions = dwOptions;
  873. LogEventInfo.iMessageString = iMessageString;
  874. LogEventInfo.hModule = hModule;
  875. // Construct the event context
  876. LogParms.pSmtpEventLogInfo = &LogEventInfo;
  877. LogParms.pDefaultEventLogHandler = &g_EventLog;
  878. LogParms.iSelectedDebugLevel = m_dwEventlogLevel;
  879. TriggerServerEvent( SMTP_LOG_EVENT, (PVOID)&LogParms );
  880. return hr;
  881. }
  882. /////////////////////////////////////////////////////////////////
  883. HRESULT SMTP_SERVER_INSTANCE::ResetLogEvent(
  884. IN DWORD idMessage,
  885. IN LPCSTR szKey)
  886. {
  887. HRESULT hr = S_OK;
  888. hr = g_EventLog.ResetEvent(idMessage, szKey);
  889. return hr;
  890. }
  891. /////////////////////////////////////////////////////////////////
  892. HRESULT SMTP_SERVER_INSTANCE::HrTriggerGetAuxDomainInfoFlagsEvent(
  893. IN LPCSTR pszDomainName,
  894. OUT DWORD *pdwDomainInfoFlags )
  895. {
  896. HRESULT hr = S_OK;
  897. EVENTPARAMS_GET_AUX_DOMAIN_INFO_FLAGS EventParams;
  898. DWORD dwStartTicks, dwStopTicks;
  899. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE:HrTriggerGetAuxDomainInfoFlagsEvent" );
  900. _ASSERT(pdwDomainInfoFlags);
  901. // Before we trigger the event, let's pre-set pdwDomainInfoFlags
  902. // to be "DOMAIN_INFO_INVALID" so we get the right result if there
  903. // were no sinks
  904. *pdwDomainInfoFlags = DOMAIN_INFO_INVALID;
  905. // Construct the event params
  906. EventParams.pIServer = GetInstancePropertyBag();
  907. EventParams.pszDomainName = pszDomainName;
  908. EventParams.pdwDomainInfoFlags = pdwDomainInfoFlags;
  909. DebugTrace((LPARAM)this, "Triggering event SMTP_GET_AUX_DOMAIN_INFO_FLAGS_EVENT ...");
  910. // Count ticks for calling this event
  911. dwStartTicks = GetTickCount();
  912. hr = TriggerServerEvent( SMTP_GET_AUX_DOMAIN_INFO_FLAGS_EVENT, (PVOID)&EventParams );
  913. if(FAILED(hr)) {
  914. goto Exit;
  915. }
  916. dwStopTicks = GetTickCount();
  917. DebugTrace((LPARAM)this, "Event SMTP_GET_AUX_DOMAIN_INFO_FLAGS_EVENT took %d ms.",
  918. dwStopTicks - dwStartTicks);
  919. if (*EventParams.pdwDomainInfoFlags & DOMAIN_INFO_INVALID) {
  920. // domain info not found ... the caller can interpret the flags
  921. DebugTrace((LPARAM)this, "Event SMTP_GET_AUX_DOMAIN_INFO_FLAGS_EVENT did NOT return data");
  922. hr = S_OK;
  923. }
  924. else {
  925. DebugTrace((LPARAM)this, "Event SMTP_GET_AUX_DOMAIN_INFO_FLAGS_EVENT returned flags : %d", *EventParams.pdwDomainInfoFlags);
  926. hr = S_OK;
  927. }
  928. Exit:
  929. TraceFunctLeaveEx((LPARAM) this);
  930. return hr;
  931. }
  932. /////////////////////////////////////////////////////////////////
  933. HRESULT SMTP_SERVER_INSTANCE::TriggerServerEvent(DWORD dwEventID, PVOID pvContext)
  934. {
  935. return m_CSMTPSeoMgr.HrTriggerServerEvent(dwEventID, pvContext);
  936. }
  937. /////////////////////////////////////////////////////////////////
  938. //--------------------------------------------------------------------------------------
  939. // Description:
  940. // Performs per-startup initialization of SMTP_SERVER_INSTANCE. All initialization
  941. // in here is de-inited by InitiateShutDown(). IIS calls this function each time
  942. // a VSI is started up.
  943. // Arguments:
  944. // None.
  945. // Returns:
  946. // TRUE on success, FALSE otherwise.
  947. // Notes:
  948. // InitiateStartup() and InitiateShutdown() could be called multiple times for the
  949. // same SMTP_SERVER_INSTANCE by IIS. If this fails, IIS will shutdown the VSI by
  950. // calling InitiateShutdown().
  951. //--------------------------------------------------------------------------------------
  952. BOOL SMTP_SERVER_INSTANCE::InitiateStartup(void)
  953. {
  954. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE:InitiateStartup" );
  955. DWORD error = NO_ERROR, err = NO_ERROR;
  956. CSMTPServer * Ptr = NULL;
  957. HRESULT hr = S_OK;
  958. EnterCriticalSection( &m_critBoot );
  959. InitializeClassVariables();
  960. Ptr = new CSMTPServer();
  961. if (Ptr != NULL) {
  962. Ptr->Init(this);
  963. hr = Ptr->QueryInterface(IID_ISMTPServer, (void **) &m_ComSmtpServer);
  964. if (FAILED(hr) || !m_ComSmtpServer) {
  965. err = GetLastError();
  966. ErrorTrace((LPARAM) this, "QueryInterface for m_ComSmtpServer failed - %x", hr);
  967. goto error_exit;
  968. }
  969. } else {
  970. ErrorTrace((LPARAM) this, "new CSMTPServer() failed");
  971. err = ERROR_NOT_ENOUGH_MEMORY;
  972. goto error_exit;
  973. }
  974. m_QStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  975. if (m_QStopEvent == NULL) {
  976. err = GetLastError();
  977. ErrorTrace((LPARAM) this, "Creating stop event failed - %d", err);
  978. goto error_exit;
  979. }
  980. //
  981. // Create statistics object before initializing the queues
  982. //
  983. m_pSmtpStats = new SMTP_SERVER_STATISTICS(this);
  984. if ( m_pSmtpStats == NULL ) {
  985. err = ERROR_NOT_ENOUGH_MEMORY;
  986. ErrorTrace((LPARAM) this, "new SMTP_SERVER_STATISTICS(this) failed - %d", err);
  987. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  988. goto error_exit;
  989. }
  990. //
  991. // initialize the info list - used to collect performance info (a bit of a backdoor
  992. // to get the information back
  993. //
  994. if (!(m_pSmtpInfo = new SMTP_INSTANCE_LIST_ENTRY)) {
  995. ErrorTrace((LPARAM) this, "new SMTP_INSTANCE_LIST_ENTRY failed");
  996. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  997. goto error_exit;
  998. }
  999. m_pSmtpInfo->dwInstanceId = QueryInstanceId();
  1000. m_pSmtpInfo->pSmtpServerStatsObj = m_pSmtpStats;
  1001. ((PSMTP_IIS_SERVICE) g_pInetSvc)->AcquireServiceExclusiveLock();
  1002. InsertTailList((((PSMTP_IIS_SERVICE) g_pInetSvc)->GetInfoList()), &(m_pSmtpInfo->ListEntry));
  1003. ((PSMTP_IIS_SERVICE) g_pInetSvc)->ReleaseServiceExclusiveLock();
  1004. ((PSMTP_IIS_SERVICE) g_pInetSvc)->StartHintFunction();
  1005. //
  1006. // shinjuku initialization
  1007. //
  1008. hr = m_CSMTPSeoMgr.HrInit(QueryInstanceId());
  1009. if (FAILED(hr)) {
  1010. char szInst[10];
  1011. _itoa((int)QueryInstanceId(), szInst, 10);
  1012. ErrorTrace((LPARAM)this, "Error: Failed to initialize SEO for instance %u",
  1013. QueryInstanceId());
  1014. SmtpLogEventEx(SEO_INIT_FAILED_INSTANCE,
  1015. szInst,
  1016. hr);
  1017. goto error_exit;
  1018. }
  1019. if (!InitFromRegistry()) {
  1020. err= GetLastError();
  1021. ErrorTrace((LPARAM) this, "init from registry failed. err = %d", err);
  1022. if (err == NO_ERROR)
  1023. err = ERROR_INVALID_PARAMETER;
  1024. SetLastError(err);
  1025. goto error_exit;
  1026. }
  1027. ((PSMTP_IIS_SERVICE) g_pInetSvc)->StartHintFunction();
  1028. TriggerStoreServerEvent(SMTP_STOREDRV_STARTUP_EVENT);
  1029. m_fStoreDrvStartEventCalled = TRUE;
  1030. // Enumerate files ...
  1031. DWORD dwThreadId;
  1032. m_hEnumBuildQ = CreateThread(
  1033. NULL,
  1034. 0,
  1035. EnumBuildQProc,
  1036. (LPVOID)this,
  1037. 0,
  1038. &dwThreadId);
  1039. if (m_hEnumBuildQ == NULL) {
  1040. err = GetLastError();
  1041. ErrorTrace((LPARAM) this, "Creating startup enumeration thread failed - %d", err);
  1042. goto error_exit;
  1043. }
  1044. // Initialize the mail pickup stuff, only if enabled
  1045. if (ShouldPickupMail() && !InitDirectoryNotification()) {
  1046. err = GetLastError();
  1047. ErrorTrace((LPARAM) this, "InitDirectoryNotification() failed. err: %u", error);
  1048. if (err == NO_ERROR)
  1049. err = ERROR_INVALID_PARAMETER;
  1050. SetLastError(err);
  1051. goto error_exit;
  1052. }
  1053. LeaveCriticalSection( &m_critBoot );
  1054. TraceFunctLeaveEx((LPARAM) this);
  1055. return TRUE;
  1056. error_exit:
  1057. LeaveCriticalSection( &m_critBoot );
  1058. TraceFunctLeaveEx((LPARAM) this);
  1059. return FALSE;
  1060. }
  1061. PSMTP_INSTANCE_LIST_ENTRY SMTP_SERVER_INSTANCE::GetSmtpInstanceInfo(void)
  1062. {
  1063. AQPerfCounters AqPerf;
  1064. HRESULT hr = S_FALSE;
  1065. if (m_pIAdvQueueConfig != NULL) {
  1066. AqPerf.cbVersion = sizeof(AQPerfCounters);
  1067. hr = m_pIAdvQueueConfig->GetPerfCounters(
  1068. &AqPerf,
  1069. (m_pSmtpInfo) ?
  1070. &(m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->CatPerfBlock) :
  1071. NULL);
  1072. }
  1073. if(!FAILED(hr))
  1074. {
  1075. if(m_pSmtpInfo)
  1076. {
  1077. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->RemoteQueueLength = AqPerf.cCurrentQueueMsgInstances;
  1078. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->NumMsgsDelivered = AqPerf.cMsgsDeliveredLocal;
  1079. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->LocalQueueLength = AqPerf.cCurrentMsgsPendingLocalDelivery;
  1080. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->RemoteRetryQueueLength = AqPerf.cCurrentMsgsPendingRemoteRetry;
  1081. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->NumSendRetries = AqPerf.cTotalMsgRemoteSendRetries;
  1082. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->NumNDRGenerated = AqPerf.cNDRsGenerated;
  1083. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->RetryQueueLength = AqPerf.cCurrentMsgsPendingLocalRetry;
  1084. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->NumDeliveryRetries = AqPerf.cTotalMsgLocalRetries;
  1085. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->ETRNMessages = AqPerf.cTotalMsgsTURNETRN;
  1086. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->CatQueueLength = AqPerf.cCurrentMsgsPendingCat;
  1087. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->MsgsBadmailNoRecipients = AqPerf.cTotalMsgsBadmailNoRecipients;
  1088. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->MsgsBadmailHopCountExceeded = AqPerf.cTotalMsgsBadmailHopCountExceeded;
  1089. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->MsgsBadmailFailureGeneral = AqPerf.cTotalMsgsBadmailFailureGeneral;
  1090. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->MsgsBadmailBadPickupFile = AqPerf.cTotalMsgsBadmailBadPickupFile;
  1091. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->MsgsBadmailEvent = AqPerf.cTotalMsgsBadmailEvent;
  1092. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->MsgsBadmailNdrOfDsn = AqPerf.cTotalMsgsBadmailNdrOfDsn;
  1093. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->MsgsPendingRouting = AqPerf.cCurrentMsgsPendingRouting;
  1094. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->MsgsPendingUnreachableLink = AqPerf.cCurrentMsgsPendingUnreachableLink;
  1095. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->SubmittedMessages = AqPerf.cTotalMsgsSubmitted;
  1096. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->DSNFailures = AqPerf.cTotalDSNFailures;
  1097. m_pSmtpInfo->pSmtpServerStatsObj->QueryStatsMember()->MsgsInLocalDelivery = AqPerf.cCurrentMsgsInLocalDelivery;
  1098. }
  1099. }
  1100. return m_pSmtpInfo;
  1101. }
  1102. //---[ SMTP_SERVER_INSTANCE::HrGetDomainInfoFlags ]----------------------------
  1103. //
  1104. //
  1105. // Description:
  1106. // Gets domain info flags for specified domain if present
  1107. // Parameters:
  1108. // IN szDomainName Name of domain to check for
  1109. // OUT pdwDomainInfoFlags DomainInfo flags for this domain
  1110. // Returns:
  1111. // S_OK on success
  1112. // E_INVALIDARG if szDomainName or pdwDomainInfoFlags is NULL
  1113. // E_FAIL if other failure
  1114. // History:
  1115. // 10/6/2000 - dbraun, Created.
  1116. //
  1117. //-----------------------------------------------------------------------------
  1118. HRESULT SMTP_SERVER_INSTANCE::HrGetDomainInfoFlags(
  1119. IN LPSTR szDomainName,
  1120. OUT DWORD *pdwDomainInfoFlags)
  1121. {
  1122. HRESULT hr = S_OK;
  1123. IAdvQueueDomainType * pIAdvQueueDomainType = NULL;
  1124. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE:HrGetDomainInfoFlags" );
  1125. // Make sure we have a valid IAdvQueue interface
  1126. if (!m_IAQ) {
  1127. ErrorTrace((LPARAM) this, "Member m_IAQ is not valid");
  1128. _ASSERT(m_IAQ);
  1129. hr = E_FAIL;
  1130. goto exit;
  1131. }
  1132. // Get the IAdvQueueDomainType interface
  1133. hr = m_IAQ->QueryInterface(IID_IAdvQueueDomainType, (void **) &pIAdvQueueDomainType);
  1134. if (FAILED(hr) || !pIAdvQueueDomainType) {
  1135. ErrorTrace((LPARAM) this, "QueryInterface for IID_IAdvQueueDomainType failed - %x", hr);
  1136. hr = E_FAIL;
  1137. goto exit;
  1138. }
  1139. // Got the interface, now check for the domain
  1140. hr = pIAdvQueueDomainType->GetDomainInfoFlags(szDomainName, pdwDomainInfoFlags);
  1141. exit:
  1142. if (pIAdvQueueDomainType)
  1143. pIAdvQueueDomainType->Release();
  1144. TraceFunctLeaveEx((LPARAM) this);
  1145. return hr;
  1146. }
  1147. BOOL SMTP_SERVER_INSTANCE::Stop(void)
  1148. {
  1149. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE:Stop" );
  1150. //set the global termination flag
  1151. m_IsShuttingDown = TRUE;
  1152. EnterCriticalSection( &m_critBoot );
  1153. if (m_ICM) {
  1154. m_ICM->ReleaseWaitingThreads();
  1155. }
  1156. if (!m_InstBooted) {
  1157. LeaveCriticalSection( &m_critBoot );
  1158. TraceFunctLeaveEx((LPARAM) this);
  1159. return TRUE;
  1160. }
  1161. if (m_fShutdownCalled) {
  1162. LeaveCriticalSection( &m_critBoot );
  1163. TraceFunctLeaveEx((LPARAM) this);
  1164. return TRUE;
  1165. }
  1166. if (m_QStopEvent) {
  1167. SetEvent(m_QStopEvent);
  1168. }
  1169. //disconnect all inbound connections
  1170. DisconnectAllConnections();
  1171. DisconnectAllAsyncDnsConnections();
  1172. //disconnect all outbound connections
  1173. DisconnectAllOutboundConnections();
  1174. DisconnectAllAsyncConnections();
  1175. //we need to disconnect all outbound connections again here,
  1176. //incase one slipped past the remote queue shutdown code
  1177. DisconnectAllOutboundConnections();
  1178. m_rfAccessCheck.Reset( (IMDCOM*)m_Service->QueryMDObject() );
  1179. LeaveCriticalSection( &m_critBoot );
  1180. TraceFunctLeaveEx((LPARAM) this);
  1181. return TRUE;
  1182. }
  1183. //-----------------------------------------------------------------------------------
  1184. // Description:
  1185. // Function called by IIS to deinitialize SMTP_SERVER_INSTANCE when the VSI is
  1186. // stopping. Note that this function can be called multiple times for the same
  1187. // SMTP_SERVER_INSTANCE. A matching call to InitializeClassVariables() and
  1188. // InitiateStartup() do is made by IIS (to start SMTP_SERVER_INSTANCE).
  1189. // Arguments:
  1190. // None.
  1191. // Returns:
  1192. // None.
  1193. //-----------------------------------------------------------------------------------
  1194. void SMTP_SERVER_INSTANCE::InitiateShutDown(void)
  1195. {
  1196. char IntBuffer [20];
  1197. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE:InitiateShutDown" );
  1198. EnterCriticalSection( &m_critBoot );
  1199. Stop();
  1200. // Wait for the enum buildq thread to die ...
  1201. if (m_hEnumBuildQ) {
  1202. DWORD dwWait;
  1203. do {
  1204. dwWait = WaitForSingleObject(m_hEnumBuildQ, 1000);
  1205. if (dwWait == WAIT_TIMEOUT)
  1206. StopHint();
  1207. } while (dwWait != WAIT_OBJECT_0);
  1208. CloseHandle(m_hEnumBuildQ);
  1209. m_hEnumBuildQ = NULL;
  1210. }
  1211. // Wait for the enum domains thread to die ...
  1212. if (m_hEnumDomainThreadHandle) {
  1213. DWORD dwWait;
  1214. do {
  1215. dwWait = WaitForSingleObject(m_hEnumDomainThreadHandle, 1000);
  1216. if (dwWait == WAIT_TIMEOUT)
  1217. StopHint();
  1218. } while (dwWait != WAIT_OBJECT_0);
  1219. CloseHandle(m_hEnumDomainThreadHandle);
  1220. m_hEnumDomainThreadHandle = NULL;
  1221. }
  1222. //make sure directory notification threads are shut down
  1223. if (ShouldPickupMail())
  1224. DestroyDirectoryNotification();
  1225. //Prepare for shutdown *must* be called before StopQDrivers... otherwise
  1226. //we may have stray threads calling into submit messages... which could
  1227. //AV.
  1228. if(m_fStoreDrvStartEventCalled && !m_fStoreDrvPrepShutDownEventCalled)
  1229. {
  1230. TriggerStoreServerEvent(SMTP_STOREDRV_PREPSHUTDOWN_EVENT);
  1231. m_fStoreDrvPrepShutDownEventCalled = TRUE;
  1232. }
  1233. // After this NOBODY can submit to the queue, the pointers are GONE
  1234. StopQDrivers();
  1235. if( m_fStoreDrvStartEventCalled )
  1236. {
  1237. TriggerStoreServerEvent(SMTP_STOREDRV_SHUTDOWN_EVENT);
  1238. }
  1239. //now that all the queues have stopped receiving data,
  1240. //flush each queue, by removing all data and then delete
  1241. //the queues.
  1242. if (m_RemoteQ != NULL) {
  1243. delete m_RemoteQ;
  1244. m_RemoteQ = NULL;
  1245. }
  1246. DebugTrace((LPARAM)this, "removing and delete the Info List");
  1247. if (m_pSmtpInfo != NULL) {
  1248. ((PSMTP_IIS_SERVICE)g_pInetSvc)->AcquireServiceExclusiveLock();
  1249. RemoveEntryList(&(m_pSmtpInfo->ListEntry));
  1250. ((PSMTP_IIS_SERVICE)g_pInetSvc)->ReleaseServiceExclusiveLock();
  1251. delete (m_pSmtpInfo);
  1252. m_pSmtpInfo = NULL;
  1253. }
  1254. DebugTrace((LPARAM)this, "deleting statistics obj");
  1255. //
  1256. // delete statistics object
  1257. //
  1258. if ( m_pSmtpStats != NULL ) {
  1259. delete m_pSmtpStats;
  1260. m_pSmtpStats = NULL;
  1261. }
  1262. FreeVRootList(&m_leVRoots);
  1263. DebugTrace((LPARAM)this, "deleting crit sects");
  1264. //Delete the critical section objects
  1265. if (m_SmtpInitializeStatus & SMTP_INIT_CSLOCK) {
  1266. DeleteCriticalSection( &m_csLock);
  1267. m_SmtpInitializeStatus &= ~SMTP_INIT_CSLOCK;
  1268. }
  1269. if (m_ProviderPackages != NULL ) {
  1270. LocalFree((HANDLE)m_ProviderPackages);
  1271. m_ProviderPackages = NULL;
  1272. }
  1273. //free the SSL info object
  1274. if ( m_pSSLInfo != NULL ) {
  1275. //If the refcount is not zero - we have a problem
  1276. DWORD dwCount = IIS_SSL_INFO::Release( m_pSSLInfo );
  1277. m_pSSLInfo = NULL;
  1278. }
  1279. ResetRelayIpSecList();
  1280. //
  1281. // shutdown shinjuku
  1282. // this causes SEO to drop all loaded objects
  1283. //
  1284. m_CSMTPSeoMgr.Deinit();
  1285. if (m_ComSmtpServer != NULL) {
  1286. m_ComSmtpServer->Release();
  1287. m_ComSmtpServer = NULL;
  1288. }
  1289. if (m_QStopEvent != NULL) {
  1290. CloseHandle(m_QStopEvent);
  1291. m_QStopEvent = NULL;
  1292. }
  1293. //
  1294. // here we see if we are getting shutdown because we are being
  1295. // deleted. if so then we'll remove all of our bindings from
  1296. // the shinjuku event binding database
  1297. //
  1298. MB mb( (IMDCOM*) g_pInetSvc->QueryMDObject() );
  1299. StopHint();
  1300. if (mb.Open(QueryMDPath())) {
  1301. // our metabase path still exists, so we aren't being deleted
  1302. mb.Close();
  1303. } else {
  1304. StopHint();
  1305. // our metabase path is gone, delete the shinjuku binding
  1306. // database
  1307. HRESULT hr = UnregisterPlatSEOInstance(QueryInstanceId());
  1308. if (FAILED(hr)) {
  1309. char szInst[10];
  1310. _itoa((int)QueryInstanceId(), szInst, 10);
  1311. ErrorTrace(0, "UnregisterSEOInstance(%lu) failed with %x",
  1312. QueryInstanceId(), hr);
  1313. SmtpLogEventEx(SEO_DELETE_INSTANCE_FAILED,
  1314. szInst,
  1315. hr);
  1316. }
  1317. }
  1318. _ASSERT(m_fInitAsyncCS && "Deleting un-initialized critsec");
  1319. if(m_fInitAsyncCS) {
  1320. DeleteCriticalSection( &m_csAsyncDns);
  1321. DeleteCriticalSection( &m_csAsyncConnect);
  1322. m_fInitAsyncCS = FALSE;
  1323. }
  1324. m_fShutdownCalled = TRUE;
  1325. LeaveCriticalSection( &m_critBoot );
  1326. TraceFunctLeaveEx((LPARAM) this);
  1327. }
  1328. DWORD SMTP_SERVER_INSTANCE::PauseInstance()
  1329. {
  1330. DWORD err = NO_ERROR ;
  1331. char IntBuffer [20];
  1332. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::PauseInstance");
  1333. err = IIS_SERVER_INSTANCE::PauseInstance() ;
  1334. if (err == NO_ERROR) {
  1335. _itoa(QueryInstanceId(), IntBuffer, 10);
  1336. SmtpLogEventEx(SMTP_EVENT_SERVICE_INSTANCE_PAUSED, IntBuffer, 0);
  1337. }
  1338. TraceFunctLeaveEx((LPARAM)this);
  1339. return err ;
  1340. }
  1341. /*++
  1342. Routine Description:
  1343. Sets instance to RUNNING
  1344. Arguments:
  1345. NewState - Receives the new state.
  1346. Return Value:
  1347. DWORD - 0 if successful, !0 otherwise.
  1348. --*/
  1349. DWORD SMTP_SERVER_INSTANCE::StartInstance(void)
  1350. {
  1351. DWORD RetCode = ERROR_INVALID_SERVICE_CONTROL;
  1352. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::StartInstance(void)" );
  1353. _ASSERT(QueryServerState( ) == MD_SERVER_STATE_STOPPED);
  1354. //initiate our startup first
  1355. if ( InitiateStartup() ) {
  1356. RetCode = IIS_SERVER_INSTANCE::StartInstance();
  1357. if (RetCode != ERROR_SUCCESS) {
  1358. // shutdown the instance
  1359. InitiateShutDown();
  1360. DebugTrace((LPARAM)this, "StartInstance() failed, err= %d", RetCode);
  1361. }
  1362. else
  1363. {
  1364. m_InstBooted = TRUE;
  1365. }
  1366. } else {
  1367. //shutdown everything
  1368. InitiateShutDown();
  1369. }
  1370. TraceFunctLeaveEx((LPARAM)this);
  1371. return RetCode;
  1372. }
  1373. DWORD SMTP_SERVER_INSTANCE::StopInstance(void)
  1374. {
  1375. DWORD RetCode = NO_ERROR;
  1376. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::StopInstance(void)" );
  1377. //call the IIS stuff first.
  1378. RetCode = IIS_SERVER_INSTANCE::StopInstance();
  1379. if (RetCode == NO_ERROR) {
  1380. //shutdown everything
  1381. InitiateShutDown();
  1382. } else {
  1383. DebugTrace((LPARAM)this, "StopInstance() failed, err= %d", RetCode);
  1384. }
  1385. TraceFunctLeaveEx((LPARAM)this);
  1386. return RetCode;
  1387. }
  1388. BOOL SMTP_SERVER_INSTANCE::InitQueues(void)
  1389. {
  1390. DWORD error = NO_ERROR;
  1391. BOOL fReturn = FALSE;
  1392. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::InitQueues" );
  1393. m_RemoteQ = PERSIST_QUEUE::CreateQueue(REMOTEQ, this);
  1394. if (m_RemoteQ != NULL) {
  1395. fReturn = TRUE;
  1396. } else {
  1397. error = GetLastError();
  1398. ErrorTrace((LPARAM)this, "new failed for PERSIST_QUEUE::CreateQueue(REMOTEQ). err: %u", error);
  1399. if (error == NO_ERROR)
  1400. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  1401. }
  1402. return fReturn;
  1403. }
  1404. void SMTP_SERVER_INSTANCE::FreeVRootList(PLIST_ENTRY pleHead)
  1405. {
  1406. PLIST_ENTRY pEntry;
  1407. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::FreeVRootList" );
  1408. while (!IsListEmpty(pleHead)) {
  1409. pEntry = RemoveHeadList(pleHead);
  1410. TCP_FREE(CONTAINING_RECORD(pEntry, SMTP_VROOT_ENTRY, list));
  1411. }
  1412. TraceFunctLeaveEx((LPARAM)this);
  1413. }
  1414. BOOL
  1415. GetVroots(
  1416. PVOID pvContext,
  1417. MB * pmb,
  1418. VIRTUAL_ROOT * pvr
  1419. )
  1420. /*++
  1421. Routine Description:
  1422. Virtual directory enumerater callback that allocates and builds the
  1423. virtual directory structure list
  1424. Arguments:
  1425. pvContext is a pointer to the midl allocated memory
  1426. Return:
  1427. TRUE if success, otherwise FALSE
  1428. --*/
  1429. {
  1430. //LPINET_INFO_VIRTUAL_ROOT_LIST pvrl = (LPINET_INFO_VIRTUAL_ROOT_LIST) pv
  1431. //DWORD i = pvrl->cEntries;
  1432. //LPINET_INFO_VIRTUAL_ROOT_ENTRY pvre = &pvrl->aVirtRootEntry[i];
  1433. //_ASSERT( pvr->pszMetaPath[0] == '/' &&
  1434. // pvr->pszMetaPath[1] == '/' );
  1435. return TRUE;
  1436. }
  1437. BOOL SMTP_SERVER_INSTANCE::FindBestVRoot(LPSTR szVRoot)
  1438. {
  1439. PLIST_ENTRY pEntry;
  1440. HANDLE hToken;
  1441. DWORD cbRoot;
  1442. char szRoot[MAX_PATH + 1];
  1443. DWORD dwErr;
  1444. DWORD dwBytes;
  1445. DWORD dwSectors;
  1446. DWORD dwFree;
  1447. DWORD dwTotal;
  1448. DWORD dwRatio;
  1449. DWORD dwRatioKeep;
  1450. PLIST_ENTRY pKeep = NULL;
  1451. LPSTR szT;
  1452. DWORD cSlash;
  1453. DWORD dwAccessMask = 0;
  1454. SMTP_VROOT_ENTRY *pVrEntry = NULL;
  1455. TraceFunctEnterEx((LPARAM)this, "SMTPCONFIG::FindBestVRoot");
  1456. if (IsListEmpty(&m_leVRoots)) {
  1457. ErrorTrace((LPARAM)this, "Vroots list empty");
  1458. return FALSE;
  1459. }
  1460. for (pEntry = m_leVRoots.Flink ; pEntry != &m_leVRoots ; pEntry = pEntry->Flink) {
  1461. cbRoot = sizeof(szRoot);
  1462. pVrEntry = (SMTP_VROOT_ENTRY *) CONTAINING_RECORD(pEntry, SMTP_VROOT_ENTRY, list);
  1463. if (!QueryVrootTable()->LookupVirtualRoot(pVrEntry->szVRoot,
  1464. szRoot, &cbRoot, &dwAccessMask, NULL, NULL,
  1465. &hToken, NULL)) {
  1466. dwErr = GetLastError();
  1467. ErrorTrace(NULL, "ResolveVirtualRoot failed for %s, %u",
  1468. CONTAINING_RECORD(pEntry, SMTP_VROOT_ENTRY, list)->szVRoot, dwErr);
  1469. } else {
  1470. cSlash = 0;
  1471. if (szRoot[0] == '\\' && szRoot[1] == '\\') {
  1472. // UNC Name
  1473. DebugTrace((LPARAM)this, "Found UNC path %s", szRoot);
  1474. szT = szRoot;
  1475. while (*szT) {
  1476. if (*szT == '\\') {
  1477. cSlash++;
  1478. if (cSlash == 4) {
  1479. *(szT + 1) = '\0';
  1480. }
  1481. }
  1482. szT++;
  1483. }
  1484. if (cSlash != 4) {
  1485. lstrcat(szRoot, "\\");
  1486. }
  1487. } else {
  1488. DebugTrace((LPARAM)this, "Found normal directory: %s", szRoot);
  1489. szRoot[3] = '\0';
  1490. }
  1491. DebugTrace((LPARAM)this, "Getting free disk ratio on %s", szRoot);
  1492. if (hToken == 0 || ImpersonateLoggedOnUser(hToken)) {
  1493. if (GetDiskFreeSpace(szRoot, &dwSectors, &dwBytes, &dwFree, &dwTotal)) {
  1494. dwSectors *= dwBytes;
  1495. dwRatio = MulDiv(dwSectors, dwTotal, dwFree);
  1496. if (pKeep == NULL) {
  1497. dwRatioKeep = dwRatio;
  1498. pKeep = pEntry;
  1499. } else {
  1500. if (dwRatioKeep > dwRatio) {
  1501. dwRatioKeep = dwRatio;
  1502. pKeep = pEntry;
  1503. }
  1504. }
  1505. }
  1506. if (hToken != 0)
  1507. _VERIFY(RevertToSelf());
  1508. }
  1509. }
  1510. }
  1511. if (pKeep != NULL)
  1512. lstrcpy(szVRoot, CONTAINING_RECORD(pKeep, SMTP_VROOT_ENTRY, list)->szVRoot);
  1513. else
  1514. lstrcpy(szVRoot, pVrEntry->szVRoot);
  1515. TraceFunctLeaveEx((LPARAM)this);
  1516. return TRUE;
  1517. }
  1518. //+---------------------------------------------------------------
  1519. //
  1520. // Function: SMTPCONFIG::WriteRegParams
  1521. //
  1522. // Synopsis: Writes parameters from a config info structure
  1523. // into the registry
  1524. //
  1525. // Arguments: SMTP_CONFIG_INFO *: pointer to config information
  1526. //
  1527. // Returns: BOOL - TRUE on SUCCESS, FALSE on FAIL
  1528. //
  1529. //----------------------------------------------------------------
  1530. BOOL SMTP_SERVER_INSTANCE::WriteRegParams(SMTP_CONFIG_INFO *pconfig)
  1531. {
  1532. //TraceFunctLeaveEx((LPARAM)this);
  1533. return TRUE;
  1534. }
  1535. DWORD ReadMetabaseDword (MB& mb, DWORD Key, DWORD DefaultValue)
  1536. {
  1537. DWORD tmp = 0;
  1538. if ( !mb.GetDword("", Key, IIS_MD_UT_SERVER, &tmp)) {
  1539. //mb.SetDword("", Key, IIS_MD_UT_SERVER, DefaultValue);
  1540. tmp = DefaultValue;
  1541. }
  1542. return tmp;
  1543. }
  1544. BOOL SMTP_SERVER_INSTANCE::SetProviderPackages()
  1545. {
  1546. TraceFunctEnter( "SMTP_SERVER_INSTANCE::SetProviderPackages" );
  1547. LPSTR psz;
  1548. DWORD i;
  1549. PAUTH_BLOCK pBlock = NULL;
  1550. if ( m_ProviderNames == NULL || m_cProviderPackages == 0) {
  1551. ErrorTrace((LPARAM)this, "Invalid Parameters: 0x%08X, %d",
  1552. m_ProviderNames, m_cProviderPackages );
  1553. return FALSE;
  1554. }
  1555. pBlock = (PAUTH_BLOCK)LocalAlloc(0, m_cProviderPackages * sizeof(AUTH_BLOCK));
  1556. if (pBlock == NULL) {
  1557. ErrorTrace( 0, "AUTH_BLOCK LocalAlloc failed: %d", GetLastError() );
  1558. return FALSE;
  1559. }
  1560. //
  1561. // start at 1 since 0 indicates the Invalid protocol
  1562. //
  1563. for ( i=0, psz = (LPSTR)m_ProviderNames; i< m_cProviderPackages; i++ ) {
  1564. //
  1565. // this would be the place to check whether the package was valid
  1566. //
  1567. DebugTrace( 0, "Protocol: %s", psz);
  1568. pBlock[i].Name = psz;
  1569. psz += lstrlen(psz) + 1;
  1570. }
  1571. //
  1572. // if we're replacing already set packages; free their memory
  1573. //
  1574. if (m_ProviderPackages != NULL ) {
  1575. LocalFree((HANDLE)m_ProviderPackages );
  1576. m_ProviderPackages = NULL;
  1577. }
  1578. m_ProviderPackages = pBlock;
  1579. return TRUE;
  1580. } // SetAuthPackageNames
  1581. /*******************************************************************
  1582. NAME: GetDefaultDomainName
  1583. SYNOPSIS: Fills in the given array with the name of the default
  1584. domain to use for logon validation.
  1585. ENTRY: pszDomainName - Pointer to a buffer that will receive
  1586. the default domain name.
  1587. cchDomainName - The size (in charactesr) of the domain
  1588. name buffer.
  1589. RETURNS: APIERR - 0 if successful, !0 if not.
  1590. HISTORY:
  1591. KeithMo 05-Dec-1994 Created.
  1592. ********************************************************************/
  1593. APIERR
  1594. GetDefaultDomainName(
  1595. STR * pstrDomainName
  1596. )
  1597. {
  1598. OBJECT_ATTRIBUTES ObjectAttributes;
  1599. NTSTATUS NtStatus;
  1600. INT Result;
  1601. APIERR err = 0;
  1602. LSA_HANDLE LsaPolicyHandle = NULL;
  1603. PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo = NULL;
  1604. TraceFunctEnter("GetDefaultDomainName");
  1605. //
  1606. // Open a handle to the local machine's LSA policy object.
  1607. //
  1608. InitializeObjectAttributes( &ObjectAttributes, // object attributes
  1609. NULL, // name
  1610. 0L, // attributes
  1611. NULL, // root directory
  1612. NULL ); // security descriptor
  1613. NtStatus = LsaOpenPolicy( NULL, // system name
  1614. &ObjectAttributes, // object attributes
  1615. POLICY_EXECUTE, // access mask
  1616. &LsaPolicyHandle ); // policy handle
  1617. if ( !NT_SUCCESS( NtStatus ) ) {
  1618. DebugTrace(0,"cannot open lsa policy, error %08lX\n",NtStatus );
  1619. err = LsaNtStatusToWinError( NtStatus );
  1620. goto Cleanup;
  1621. }
  1622. //
  1623. // Query the domain information from the policy object.
  1624. //
  1625. NtStatus = LsaQueryInformationPolicy( LsaPolicyHandle,
  1626. PolicyAccountDomainInformation,
  1627. (PVOID *)&DomainInfo );
  1628. if ( !NT_SUCCESS( NtStatus ) ) {
  1629. DebugTrace(0,"cannot query lsa policy info, error %08lX\n",NtStatus );
  1630. err = LsaNtStatusToWinError( NtStatus );
  1631. goto Cleanup;
  1632. }
  1633. //
  1634. // Compute the required length of the ANSI name.
  1635. //
  1636. Result = WideCharToMultiByte( CP_ACP,
  1637. 0, // dwFlags
  1638. (LPCWSTR)DomainInfo->DomainName.Buffer,
  1639. DomainInfo->DomainName.Length /sizeof(WCHAR),
  1640. NULL, // lpMultiByteStr
  1641. 0, // cchMultiByte
  1642. NULL, // lpDefaultChar
  1643. NULL // lpUsedDefaultChar
  1644. );
  1645. if ( Result <= 0 ) {
  1646. err = GetLastError();
  1647. goto Cleanup;
  1648. }
  1649. //
  1650. // Resize the output string as appropriate, including room for the
  1651. // terminating '\0'.
  1652. //
  1653. if ( !pstrDomainName->Resize( (UINT)Result + 1 ) ) {
  1654. err = GetLastError();
  1655. goto Cleanup;
  1656. }
  1657. //
  1658. // Convert the name from UNICODE to ANSI.
  1659. //
  1660. Result = WideCharToMultiByte( CP_ACP,
  1661. 0, // flags
  1662. (LPCWSTR)DomainInfo->DomainName.Buffer,
  1663. DomainInfo->DomainName.Length /sizeof(WCHAR),
  1664. pstrDomainName->QueryStr(),
  1665. pstrDomainName->QuerySize() - 1, // for '\0'
  1666. NULL,
  1667. NULL
  1668. );
  1669. if ( Result <= 0 ) {
  1670. err = GetLastError();
  1671. DebugTrace(0,"cannot convert domain name to ANSI, error %d\n",err );
  1672. goto Cleanup;
  1673. }
  1674. //
  1675. // Ensure the ANSI string is zero terminated.
  1676. //
  1677. _ASSERT( (DWORD)Result < pstrDomainName->QuerySize() );
  1678. pstrDomainName->QueryStr()[Result] = '\0';
  1679. //
  1680. // Success!
  1681. //
  1682. _ASSERT( err == 0 );
  1683. DebugTrace(0,"GetDefaultDomainName: default domain = %s\n",pstrDomainName->QueryStr() );
  1684. Cleanup:
  1685. if ( DomainInfo != NULL ) {
  1686. LsaFreeMemory( (PVOID)DomainInfo );
  1687. }
  1688. if ( LsaPolicyHandle != NULL ) {
  1689. LsaClose( LsaPolicyHandle );
  1690. }
  1691. return err;
  1692. } // GetDefaultDomainName()
  1693. DWORD
  1694. SMTP_SERVER_INSTANCE::ReadAuthentInfo(void)
  1695. /*++
  1696. Reads per-instance authentication info from the metabase.
  1697. Arguments:
  1698. ReadAll - If TRUE, then all authentication related items are
  1699. read from the metabase. If FALSE, then only a single item
  1700. is read.
  1701. SingleItemToRead - The single authentication item to read if
  1702. ReadAll is FALSE. Ignored if ReadAll is TRUE.
  1703. Notify - If TRUE, this is a MB notification
  1704. Returns:
  1705. DWORD - 0 if successful, !0 otherwise.
  1706. --*/
  1707. {
  1708. DWORD err = NO_ERROR;
  1709. BOOL rebuildAcctDesc = FALSE;
  1710. TCP_AUTHENT_INFO* pTcpAuthentInfo = NULL;
  1711. MB mb( (IMDCOM*)g_pInetSvc->QueryMDObject() );
  1712. TraceFunctEnter("SMTP_SERVER_INSTANCE::ReadAuthentInfo");
  1713. //
  1714. // Lock our configuration (since we'll presumably be making changes)
  1715. // and open the metabase.
  1716. //
  1717. m_GenLock.ExclusiveLock();
  1718. if ( !mb.Open( QueryMDPath() ) ) {
  1719. err = GetLastError();
  1720. DebugTrace(0,"ReadAuthentInfo: cannot open metabase, error %lx\n",err);
  1721. m_GenLock.ExclusiveUnlock();
  1722. return ERROR_PATH_NOT_FOUND;
  1723. }
  1724. pTcpAuthentInfo = &m_TcpAuthentInfo ;
  1725. //
  1726. // Read the anonymous username if necessary. Note this is a REQUIRED
  1727. // property. If it is missing from the metabase, bail.
  1728. //
  1729. if ( mb.GetStr("",MD_ANONYMOUS_USER_NAME, IIS_MD_UT_SERVER,&(pTcpAuthentInfo->strAnonUserName)
  1730. ) ) {
  1731. rebuildAcctDesc = TRUE;
  1732. } else {
  1733. err = GetLastError();
  1734. DebugTrace(0,"ReadAuthentInfo: cannot read MD_ANONYMOUS_USER_NAME, error %lx\n",err);
  1735. }
  1736. //
  1737. // Read the "use subauthenticator" flag if necessary. This is an
  1738. // optional property.
  1739. //
  1740. if ( err == NO_ERROR) {
  1741. (pTcpAuthentInfo->fDontUseAnonSubAuth) = ReadMetabaseDword (mb, MD_ANONYMOUS_USE_SUBAUTH, DEFAULT_USE_SUBAUTH);
  1742. }
  1743. //
  1744. // Read the anonymous password if necessary. This is an optional
  1745. // property.
  1746. //
  1747. if ( err == NO_ERROR ) {
  1748. if ( mb.GetStr(
  1749. "",
  1750. MD_ANONYMOUS_PWD,
  1751. IIS_MD_UT_SERVER,
  1752. &(pTcpAuthentInfo->strAnonUserPassword),
  1753. METADATA_INHERIT,
  1754. DEFAULT_ANONYMOUS_PWD
  1755. ) ) {
  1756. rebuildAcctDesc = TRUE;
  1757. } else {
  1758. //
  1759. // Since we provided a default value to mb.GetStr(), it should
  1760. // only fail if something catastrophic occurred, such as an
  1761. // out of memory condition.
  1762. //
  1763. err = GetLastError();
  1764. DebugTrace(0,"ReadAuthentInfo: cannot read MD_ANONYMOUS_PWD, error %lx\n",err);
  1765. }
  1766. }
  1767. //
  1768. // Read the default logon domain if necessary. This is an optional
  1769. // property.
  1770. //
  1771. if ( err == NO_ERROR ) {
  1772. if ( !mb.GetStr(
  1773. "",
  1774. MD_DEFAULT_LOGON_DOMAIN,
  1775. IIS_MD_UT_SERVER,
  1776. &(pTcpAuthentInfo->strDefaultLogonDomain)
  1777. ) ) {
  1778. //
  1779. // Generate a default domain name.
  1780. //
  1781. err = GetDefaultDomainName( &(pTcpAuthentInfo->strDefaultLogonDomain) );
  1782. if ( err != NO_ERROR ) {
  1783. DebugTrace(0,"ReadAuthentInfo: cannot get default domain name, error %d\n",err);
  1784. }
  1785. }
  1786. }
  1787. //
  1788. // Read the logon method if necessary. This is an optional property.
  1789. //
  1790. if ( err == NO_ERROR) {
  1791. pTcpAuthentInfo->dwLogonMethod = ReadMetabaseDword (mb, MD_LOGON_METHOD, DEFAULT_LOGON_METHOD);
  1792. }
  1793. //
  1794. // If anything changed that could affect the anonymous account
  1795. // descriptor, then rebuild the descriptor.
  1796. //
  1797. if ( err == NO_ERROR && rebuildAcctDesc ) {
  1798. if ( !BuildAnonymousAcctDesc( pTcpAuthentInfo ) ) {
  1799. DebugTrace(0,"ReadAuthentInfo: BuildAnonymousAcctDesc() failed\n");
  1800. err = ERROR_NOT_ENOUGH_MEMORY; // SWAG
  1801. }
  1802. }
  1803. m_GenLock.ExclusiveUnlock();
  1804. return err;
  1805. } // SMTP_SERVER_INSTANCE::ReadAuthentInfo
  1806. //+---------------------------------------------------------------
  1807. //
  1808. // Function: SMTPCONFIG::ReadRegParams
  1809. //
  1810. // Synopsis: Reads parameters from the registry into the config
  1811. // class member variables and IServer (m_InstancePropertyBag)
  1812. //
  1813. // Arguments: FIELD_CONTROL: Bit-field defining what params to
  1814. // read.
  1815. //
  1816. // Returns: BOOL - TRUE on SUCCESS, FALSE on FAIL
  1817. //
  1818. // Note: BOOL fInit argument removed by KeithLau on 7/15/96
  1819. //
  1820. //----------------------------------------------------------------
  1821. BOOL SMTP_SERVER_INSTANCE::ReadRegParams(
  1822. FIELD_CONTROL fc, BOOL fRebuild, BOOL fShowEvents)
  1823. {
  1824. BOOL fRet = TRUE;
  1825. DWORD dwErr = NO_ERROR;
  1826. DWORD dwAttr;
  1827. DWORD dwLen;
  1828. DWORD dwTempVar;
  1829. DWORD dwAqueueWait = 0;
  1830. MB mb( (IMDCOM*)g_pInetSvc->QueryMDObject() );
  1831. char ScratchBuffer [400];
  1832. STR TempString;
  1833. const CHAR * apszSubStrings[4];
  1834. CHAR pchAddr1[32] = "";
  1835. AQConfigInfo AQConfig;
  1836. HRESULT hr;
  1837. char szDomainName[MAX_PATH + 1] = {0};
  1838. TraceFunctEnterEx((LPARAM)this, "SMTPCONFIG::SMTP_SERVER_INSTANCE");
  1839. SetLastError(NO_ERROR);
  1840. m_fDefaultInRt = FALSE;
  1841. ZeroMemory(&AQConfig, sizeof(AQConfig));
  1842. // Make sure we've got a valid field control input
  1843. _ASSERT(fc != 0 && !(fc & ~(FC_SMTP_INFO_ALL)));
  1844. m_GenLock.ExclusiveLock();
  1845. _itoa(QueryInstanceId(), pchAddr1, 10);
  1846. //
  1847. // Read metabase data.
  1848. //
  1849. if ( !mb.Open( QueryMDPath(), METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE) ) {
  1850. m_GenLock.ExclusiveUnlock();
  1851. return FALSE;
  1852. }
  1853. if (IsFieldSet(fc, FC_SMTP_INFO_ROUTING)) {
  1854. GetCatInfo(mb, AQConfig);
  1855. }
  1856. ZeroMemory(&AQConfig, sizeof(AQConfig));
  1857. if (IsFieldSet(fc, FC_SMTP_INFO_REVERSE_LOOKUP)) {
  1858. dwTempVar = 0;
  1859. dwTempVar = ReadMetabaseDword(mb, MD_REVERSE_NAME_LOOKUP, 0);
  1860. // If the value is changing, generate an information NT event...
  1861. if (dwTempVar != m_RDNSOptions) {
  1862. apszSubStrings[0] = pchAddr1;
  1863. if (fShowEvents) {
  1864. if (dwTempVar)
  1865. SmtpLogEvent(SMTP_EVENT_SET_REVERSE_LOOKUP_ENABLED, 1, apszSubStrings, 0);
  1866. else
  1867. SmtpLogEvent(SMTP_EVENT_SET_REVERSE_LOOKUP_DISABLED, 1, apszSubStrings, 0);
  1868. }
  1869. m_RDNSOptions = dwTempVar;
  1870. StateTrace((LPARAM)this, "m_fEnableReverseLookup = %u", m_RDNSOptions);
  1871. }
  1872. }
  1873. //I am isung this for all commands
  1874. if (IsFieldSet(fc, FC_SMTP_INFO_INBOUND_SUPPORT_OPTIONS)) {
  1875. m_InboundCmdOptions = ReadMetabaseDword(mb, MD_INBOUND_COMMAND_SUPPORT_OPTIONS, SMTP_DEFAULT_CMD_SUPPORT);
  1876. m_OutboundCmdOptions = ReadMetabaseDword(mb, MD_OUTBOUND_COMMAND_SUPPORT_OPTIONS, SMTP_DEFAULT_OUTBOUND_SUPPORT);
  1877. m_fAddNoHdrs = !!ReadMetabaseDword(mb, MD_ADD_NOHEADERS, FALSE);
  1878. }
  1879. if (IsFieldSet(fc, FC_SMTP_INFO_SSL_PERM)) {
  1880. BOOL fRequiresCertVerifySubject;
  1881. BOOL fRequiresCertVerifyIssuer;
  1882. fRequiresCertVerifyIssuer =
  1883. ReadMetabaseDword (mb, MD_SMTP_SSL_REQUIRE_TRUSTED_CA, FALSE);
  1884. fRequiresCertVerifySubject =
  1885. ReadMetabaseDword (mb, MD_SMTP_SSL_CERT_HOSTNAME_VALIDATION, FALSE);
  1886. m_fRequiresCertVerifySubject = fRequiresCertVerifySubject;
  1887. m_fRequiresCertVerifyIssuer = fRequiresCertVerifyIssuer;
  1888. BOOL fRequiresSSL, fRequires128Bits;
  1889. dwTempVar = ReadMetabaseDword(mb, MD_SSL_ACCESS_PERM, FALSE);
  1890. fRequiresSSL = IsFieldSet(dwTempVar, MD_ACCESS_SSL);
  1891. fRequires128Bits = IsFieldSet(dwTempVar, MD_ACCESS_SSL128);
  1892. apszSubStrings[0] = pchAddr1;
  1893. // If the value is changing, generate an information NT event...
  1894. if (fShowEvents && (fRequiresSSL != m_fRequiresSSL)) {
  1895. SmtpLogEvent(
  1896. fRequiresSSL ?
  1897. SMTP_EVENT_REQUIRE_SSL_INBOUND_ENABLE :
  1898. SMTP_EVENT_REQUIRE_SSL_INBOUND_DISABLE, 1, apszSubStrings, 0);
  1899. }
  1900. m_fRequiresSSL = fRequiresSSL;
  1901. if (fShowEvents && (fRequires128Bits != m_fRequires128Bits)) {
  1902. SmtpLogEvent(
  1903. fRequires128Bits ?
  1904. SMTP_EVENT_REQUIRE_128BIT_SSL_INBOUND_ENABLE :
  1905. SMTP_EVENT_REQUIRE_128BIT_SSL_INBOUND_DISABLE, 1, apszSubStrings, 0);
  1906. }
  1907. m_fRequires128Bits = fRequires128Bits;
  1908. StateTrace((LPARAM)this,
  1909. "m_fRequiresSSL = %s, m_fRequires128Bits = %s",
  1910. m_fRequiresSSL ? "TRUE" : "FALSE",
  1911. m_fRequires128Bits ? "TRUE" : "FALSE");
  1912. }
  1913. if (IsFieldSet(fc, FC_SMTP_INFO_COMMON_PARAMS)) {
  1914. DWORD dwDomainValidationFlags = 0;
  1915. DWORD dwNameResolution = 0;
  1916. m_dwDnsFlags = ReadMetabaseDword(mb, MD_SMTP_USE_TCP_DNS, 0);
  1917. m_dwNameResolution = ReadMetabaseDword(mb, MD_NAME_RESOLUTION_TYPE, 1);
  1918. StateTrace((LPARAM)this, "m_dwNameResolution = %u", m_dwNameResolution);
  1919. m_cMaxBatchLimit = ReadMetabaseDword(mb, MD_BATCH_MSG_LIMIT, 20);
  1920. AQConfig.cMinMessagesPerConnection = m_cMaxBatchLimit;
  1921. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MIN_MSG;
  1922. AQConfig.dwConnectionWaitMilliseconds = ReadMetabaseDword(mb, MD_SMTP_AQUEUE_WAIT, 60000);
  1923. //AQConfig.dwConnectionWaitMilliseconds = INFINITE;
  1924. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_CON_WAIT;
  1925. StateTrace((LPARAM)this, "m_cMaxBatchLimit = %u", m_cMaxBatchLimit);
  1926. m_fRelayForAuthUsers = !!ReadMetabaseDword(mb, MD_SMTP_RELAY_FOR_AUTH_USERS, TRUE);
  1927. m_fIsRelayEnabled = !!ReadMetabaseDword(mb, MD_SMTP_DISABLE_RELAY, TRUE);
  1928. m_fHelloNoDomain = !!ReadMetabaseDword(mb, MD_SMTP_HELO_NODOMAIN, TRUE);
  1929. m_fMailFromNoHello = !!ReadMetabaseDword(mb, MD_SMTP_MAIL_NO_HELO, FALSE);
  1930. //Per spec these two are related
  1931. if (m_fMailFromNoHello)
  1932. m_fHelloNoDomain = TRUE;
  1933. m_fNagleIn = !!ReadMetabaseDword(mb, MD_SMTP_INBOUND_NAGLE, FALSE);
  1934. m_fNagleOut = !!ReadMetabaseDword(mb, MD_SMTP_OUTBOUND_NAGLE, FALSE);
  1935. dwDomainValidationFlags = !!ReadMetabaseDword(mb, MD_DOMAIN_VALIDATION_FLAGS, 0);
  1936. m_fHelloNoValidate = dwDomainValidationFlags & SMTP_NOVALIDATE_EHLO;
  1937. m_fMailNoValidate = dwDomainValidationFlags & SMTP_NOVALIDATE_MAIL;
  1938. m_fRcptNoValidate = dwDomainValidationFlags & SMTP_NOVALIDATE_RCPT;
  1939. m_fEtrnNoValidate = dwDomainValidationFlags & SMTP_NOVALIDATE_ETRN;
  1940. m_fPickupNoValidate = dwDomainValidationFlags & SMTP_NOVALIDATE_PKUP;
  1941. ReadRouteDomainIpSecList(mb);
  1942. // Raid 174038
  1943. m_fDisablePickupDotStuff = !!ReadMetabaseDword(mb, MD_SMTP_DISABLE_PICKUP_DOT_STUFF, FALSE);
  1944. StateTrace((LPARAM)this, "m_fDisablePickupDotStuff = %u", m_fDisablePickupDotStuff);
  1945. m_dwEventlogLevel = ReadMetabaseDword(mb,
  1946. MD_SMTP_EVENTLOG_LEVEL,
  1947. LOGEVENT_LEVEL_MEDIUM);
  1948. }
  1949. if (IsFieldSet(fc, FC_SMTP_INFO_MAX_OUT_CONN_PER_DOMAIN)) {
  1950. dwTempVar = ReadMetabaseDword(mb, MD_MAX_OUT_CONN_PER_DOMAIN, 20);
  1951. if (fShowEvents && (dwTempVar != m_cMaxOutConnectionsPerDomain)) {
  1952. _itoa(dwTempVar, ScratchBuffer, 10);
  1953. apszSubStrings[0] = pchAddr1;
  1954. apszSubStrings[1] = ScratchBuffer;
  1955. SmtpLogEvent(SMTP_EVENT_SET_MAX_CONN_PER_DOMAIN, 2, apszSubStrings, 0);
  1956. }
  1957. m_cMaxOutConnectionsPerDomain = dwTempVar;
  1958. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MAX_LINK;
  1959. AQConfig.cMaxLinkConnections = dwTempVar;
  1960. StateTrace((LPARAM)this, "m_cMaxOutConnectionsPerDomain = %u", m_cMaxOutConnectionsPerDomain);
  1961. }
  1962. if (IsFieldSet(fc, FC_SMTP_INFO_AUTHORIZATION)) {
  1963. m_dwAuth = ReadMetabaseDword(mb, MD_AUTHORIZATION, DEFAULT_AUTHENTICATION);
  1964. DebugTrace((LPARAM)this, "m_dwAuth=%u", m_dwAuth);
  1965. }
  1966. //
  1967. // update the following data members:
  1968. // m_ProviderPackages
  1969. // m_ProviderNames
  1970. // m_cProviderPackages
  1971. if (IsFieldSet(fc, FC_SMTP_INFO_NTAUTHENTICATION_PROVIDERS)) {
  1972. CHAR szAuthPack[MAX_PATH + 1];
  1973. DWORD dwLen;
  1974. TempString.Reset();
  1975. if (mb.GetStr("", MD_NTAUTHENTICATION_PROVIDERS, IIS_MD_UT_SERVER, &TempString, METADATA_INHERIT, "")) {
  1976. lstrcpyn(szAuthPack, TempString.QueryStr(), MAX_PATH);
  1977. dwLen = lstrlen(szAuthPack);
  1978. DebugTrace((LPARAM)this, "Authentication packages=%s", szAuthPack);
  1979. if (!ConvertToMultisz(m_ProviderNames, &m_cProviderPackages, szAuthPack)) {
  1980. CopyMemory(m_ProviderNames, pszPackagesDefault, ccbPackagesDefault);
  1981. m_cProviderPackages = 2;
  1982. }
  1983. } else {
  1984. DebugTrace((LPARAM)this, "Use default authentication packages=%s", pszPackagesDefault);
  1985. CopyMemory(m_ProviderNames, pszPackagesDefault, ccbPackagesDefault);
  1986. m_cProviderPackages = 1;
  1987. }
  1988. // set the AUTH_BLOCK info
  1989. if (!SetProviderPackages()) {
  1990. ErrorTrace((LPARAM)this, "Unable to allocate AUTH_BLOCK");
  1991. }
  1992. }
  1993. if (IsFieldSet(fc, FC_SMTP_INFO_SASL_LOGON_DOMAIN)) {
  1994. TempString.Reset();
  1995. if (mb.GetStr("", MD_SASL_LOGON_DOMAIN, IIS_MD_UT_SERVER, &TempString, METADATA_INHERIT, "")) {
  1996. lstrcpyn(m_szDefaultLogonDomain, TempString.QueryStr(), MAX_SERVER_NAME_LEN);
  1997. DebugTrace((LPARAM)this, "SASL logon domain =%s", m_szDefaultLogonDomain);
  1998. } else {
  1999. m_szDefaultLogonDomain[0] = '\0';
  2000. DebugTrace((LPARAM)this, "no SASL default logon domain was found");
  2001. }
  2002. }
  2003. if (IsFieldSet(fc, FC_SMTP_CLEARTEXT_AUTH_PROVIDER)) {
  2004. TempString.Reset();
  2005. m_cbCleartextAuthPackage = sizeof(m_szCleartextAuthPackage);
  2006. if (mb.GetStr("", MD_SMTP_CLEARTEXT_AUTH_PROVIDER, IIS_MD_UT_SERVER, &TempString, METADATA_INHERIT, "")) {
  2007. lstrcpy(m_szCleartextAuthPackage, TempString.QueryStr());
  2008. m_cbCleartextAuthPackage = lstrlen(m_szCleartextAuthPackage) + 1;
  2009. StateTrace((LPARAM)this, "Cleartext authentication provider: <%s>, length %u",
  2010. m_szCleartextAuthPackage,
  2011. m_cbCleartextAuthPackage);
  2012. } else {
  2013. m_szCleartextAuthPackage[0] = '\0';
  2014. m_cbCleartextAuthPackage = 0;
  2015. StateTrace((LPARAM)this, "No default cleartext authentication provider specified, using CleartextLogon");
  2016. }
  2017. TempString.Reset();
  2018. if (mb.GetStr("", MD_MD_SERVER_SS_AUTH_MAPPING, IIS_MD_UT_SERVER, &TempString, METADATA_INHERIT, "")) {
  2019. lstrcpyn(m_szMembershipBroker, TempString.QueryStr(), MAX_PATH);
  2020. StateTrace((LPARAM)this, "Membership Broker name is set to %s", m_szMembershipBroker);
  2021. } else {
  2022. m_szMembershipBroker[0] = '\0';
  2023. StateTrace((LPARAM)this, "No Membership Broker name configured");
  2024. }
  2025. }
  2026. if (IsFieldSet(fc, FC_SMTP_INFO_MAX_HOP_COUNT)) {
  2027. dwTempVar = ReadMetabaseDword(mb, MD_HOP_COUNT, 15);
  2028. StateTrace((LPARAM)this, "m_cMaxHopCount = %u", dwTempVar);
  2029. if (fShowEvents && (dwTempVar != m_cMaxHopCount)) {
  2030. _itoa(dwTempVar, ScratchBuffer, 10);
  2031. apszSubStrings[0] = pchAddr1;
  2032. apszSubStrings[1] = ScratchBuffer;
  2033. SmtpLogEvent(SMTP_EVENT_SET_MAX_HOPCOUNT, 2, apszSubStrings, 0);
  2034. }
  2035. m_cMaxHopCount = dwTempVar;
  2036. }
  2037. if (IsFieldSet(fc, FC_SMTP_INFO_REMOTE_PORT)) {
  2038. dwTempVar = ReadMetabaseDword(mb, MD_REMOTE_SMTP_PORT, 25);
  2039. if (fShowEvents && (dwTempVar != m_RemoteSmtpPort)) {
  2040. _itoa(dwTempVar, ScratchBuffer, 10);
  2041. apszSubStrings[0] = pchAddr1;
  2042. apszSubStrings[1] = ScratchBuffer;
  2043. SmtpLogEvent(SMTP_EVENT_SET_REMOTE_PORT, 2, apszSubStrings, 0);
  2044. }
  2045. m_RemoteSmtpPort = dwTempVar;
  2046. StateTrace((LPARAM)this, "m_RemoteSmtpPort = %u", m_RemoteSmtpPort);
  2047. }
  2048. if (IsFieldSet(fc, FC_SMTP_INFO_MAX_ERRORS)) {
  2049. dwTempVar = ReadMetabaseDword(mb, MD_MAX_SMTP_ERRORS, 10);
  2050. if (dwTempVar == 0)
  2051. dwTempVar = 10;
  2052. if (fShowEvents && (dwTempVar != m_cMaxErrors)) {
  2053. _itoa(dwTempVar, ScratchBuffer, 10);
  2054. apszSubStrings[0] = pchAddr1;
  2055. apszSubStrings[1] = ScratchBuffer;
  2056. SmtpLogEvent(SMTP_EVENT_SET_MAX_ERRORS, 2, apszSubStrings, 0);
  2057. }
  2058. m_cMaxErrors = dwTempVar;
  2059. StateTrace((LPARAM)this, "m_cMaxErrors = %u", m_cMaxErrors);
  2060. dwTempVar = ReadMetabaseDword(mb, MD_MAX_SMTP_AUTHLOGON_ERRORS, 4);
  2061. if (dwTempVar == 0)
  2062. dwTempVar = 4;
  2063. if (fShowEvents && (dwTempVar != m_dwMaxLogonFailures)) {
  2064. //_itoa(dwTempVar, ScratchBuffer, 10);
  2065. // apszSubStrings[0] = pchAddr1;
  2066. // apszSubStrings[1] = ScratchBuffer;
  2067. //SmtpLogEvent(SMTP_EVENT_SET_MAX_ERRORS, 2, apszSubStrings, 0);
  2068. }
  2069. m_dwMaxLogonFailures = dwTempVar;
  2070. StateTrace((LPARAM)this, "m_dwMaxLogonFailures = %u", m_dwMaxLogonFailures);
  2071. }
  2072. if (IsFieldSet(fc, FC_SMTP_INFO_MAX_SIZE)) {
  2073. dwTempVar = ReadMetabaseDword(mb, MD_MAX_MSG_SIZE, 2 * 1024);
  2074. if (fShowEvents && (dwTempVar != m_cbMaxMsgSize)) {
  2075. _itoa(dwTempVar, ScratchBuffer, 10);
  2076. apszSubStrings[0] = pchAddr1;
  2077. apszSubStrings[1] = ScratchBuffer;
  2078. SmtpLogEvent(SMTP_EVENT_SET_MAX_SIZE_ACCEPTED, 2, apszSubStrings, 0);
  2079. }
  2080. m_cbMaxMsgSize = dwTempVar;
  2081. StateTrace((LPARAM)this, "m_cbMaxMsgSize = %u", m_cbMaxMsgSize);
  2082. dwTempVar = ReadMetabaseDword(mb, MD_MAX_MSG_SIZE_B4_CLOSE, 10 * 1024);
  2083. if (fShowEvents && (dwTempVar != m_cbMaxMsgSizeBeforeClose)) {
  2084. _itoa(dwTempVar, ScratchBuffer, 10);
  2085. apszSubStrings[0] = pchAddr1;
  2086. apszSubStrings[1] = ScratchBuffer;
  2087. SmtpLogEvent(SMTP_EVENT_SET_MAX_SIZE_BEFORE_CLOSE, 2, apszSubStrings, 0);
  2088. }
  2089. m_cbMaxMsgSizeBeforeClose = dwTempVar;
  2090. StateTrace((LPARAM)this, "m_cbMaxMsgSizeBeforeClose = %u", m_cbMaxMsgSizeBeforeClose);
  2091. }
  2092. if (IsFieldSet(fc, FC_SMTP_INFO_REMOTE_TIMEOUT)) {
  2093. dwTempVar = ReadMetabaseDword(mb, MD_REMOTE_TIMEOUT, 600);
  2094. if (fShowEvents && (dwTempVar != m_cMaxRemoteTimeOut)) {
  2095. _itoa(dwTempVar, ScratchBuffer, 10);
  2096. apszSubStrings[0] = pchAddr1;
  2097. apszSubStrings[1] = ScratchBuffer;
  2098. SmtpLogEvent(SMTP_EVENT_SET_MAX_REMOTE_TIMEOUT, 2, apszSubStrings, 0);
  2099. }
  2100. m_cMaxRemoteTimeOut = dwTempVar;
  2101. StateTrace((LPARAM)this, "m_cMaxRemoteTimeOut = %u", m_cMaxRemoteTimeOut);
  2102. m_ConnectTimeout = ReadMetabaseDword(mb, MD_SMTP_CONNECT_TIMEOUT, 150);
  2103. if (m_ConnectTimeout == 0)
  2104. m_ConnectTimeout = 1;
  2105. // Calculate timeout in milliseconds from timeout in seconds.
  2106. m_ConnectTimeout = m_ConnectTimeout * 60 * 1000;
  2107. m_MailFromTimeout = ReadMetabaseDword(mb, MD_SMTP_MAILFROM_TIMEOUT, 600);
  2108. m_RcptToTimeout = ReadMetabaseDword(mb, MD_SMTP_RCPTTO_TIMEOUT, 600);
  2109. m_DataTimeout = ReadMetabaseDword(mb, MD_SMTP_DATA_TIMEOUT, 600);
  2110. m_AuthTimeout = ReadMetabaseDword(mb, MD_SMTP_AUTH_TIMEOUT, 600);
  2111. m_SaslTimeout = ReadMetabaseDword(mb, MD_SMTP_SASL_TIMEOUT, 600);
  2112. m_HeloTimeout = ReadMetabaseDword(mb, MD_SMTP_HELO_TIMEOUT, 600);
  2113. m_BdatTimeout = ReadMetabaseDword(mb, MD_SMTP_BDAT_TIMEOUT, 600);
  2114. m_TurnTimeout = ReadMetabaseDword(mb, MD_SMTP_TURN_TIMEOUT, 600);
  2115. m_RSetTimeout = ReadMetabaseDword(mb, MD_SMTP_RSET_TIMEOUT, 600);
  2116. m_QuitTimeout = ReadMetabaseDword(mb, MD_SMTP_RSET_TIMEOUT, 600);
  2117. }
  2118. if (IsFieldSet(fc, FC_SMTP_INFO_MAX_OUTBOUND_CONN)) {
  2119. dwTempVar = ReadMetabaseDword(mb, MD_MAX_OUTBOUND_CONNECTION, 100);
  2120. if (fShowEvents && (dwTempVar != m_cMaxOutConnections)) {
  2121. _itoa(dwTempVar, ScratchBuffer, 10);
  2122. apszSubStrings[0] = pchAddr1;
  2123. apszSubStrings[1] = ScratchBuffer;
  2124. SmtpLogEvent(SMTP_EVENT_SET_MAX_OUTBOUND_CONNECTIONS, 2, apszSubStrings, 0);
  2125. }
  2126. m_cMaxOutConnections = dwTempVar;
  2127. AQConfig.cMaxConnections = dwTempVar;
  2128. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MAX_CON;
  2129. StateTrace((LPARAM)this, "m_cMaxOutConnections = %u", m_cMaxOutConnections);
  2130. }
  2131. if (IsFieldSet(fc, FC_SMTP_INFO_MAX_RECIPS)) {
  2132. dwTempVar = ReadMetabaseDword(mb, MD_MAX_RECIPIENTS, 100);
  2133. if (fShowEvents && (dwTempVar != m_cMaxRcpts)) {
  2134. _itoa(dwTempVar, ScratchBuffer, 10);
  2135. apszSubStrings[0] = pchAddr1;
  2136. apszSubStrings[1] = ScratchBuffer;
  2137. SmtpLogEvent(SMTP_EVENT_SET_MAX_RECIPIENTS, 2, apszSubStrings, 0);
  2138. }
  2139. m_cMaxRcpts = dwTempVar;
  2140. StateTrace((LPARAM)this, "m_cMaxRcpts = %u", m_cMaxRcpts);
  2141. }
  2142. if (IsFieldSet(fc, FC_SMTP_INFO_ETRN_SUBDOMAINS)) {
  2143. m_fAllowEtrnSubDomains = !!ReadMetabaseDword(mb, MD_ETRN_SUBDOMAINS, TRUE);
  2144. StateTrace((LPARAM)this, "m_fAllowEtrnSubDomains = %u", m_fAllowEtrnSubDomains);
  2145. }
  2146. if (IsFieldSet(fc, FC_SMTP_INFO_RETRY)) {
  2147. DWORD dwTempVar2 = 0;
  2148. char ScratchBuffer2[50];
  2149. dwTempVar = ReadMetabaseDword(mb, MD_LOCAL_RETRY_ATTEMPTS, 48);
  2150. dwTempVar2 = ReadMetabaseDword(mb, MD_LOCAL_RETRY_MINUTES, 60);
  2151. if (fShowEvents && ((m_cRetryAttempts != dwTempVar) ||(m_cRetryMinutes != dwTempVar2))) {
  2152. _itoa(dwTempVar, ScratchBuffer, 10);
  2153. _itoa(dwTempVar2, ScratchBuffer2, 10);
  2154. apszSubStrings[0] = pchAddr1;
  2155. apszSubStrings[1] = "Local";
  2156. apszSubStrings[2] = ScratchBuffer;
  2157. apszSubStrings[3] = ScratchBuffer2;
  2158. SmtpLogEvent(SMTP_EVENT_SET_RETRY_PARAMETERS, 4, apszSubStrings, 0);
  2159. }
  2160. m_cRetryAttempts = dwTempVar;
  2161. m_cRetryMinutes = dwTempVar2;
  2162. StateTrace((LPARAM)this, "m_cRetryAttempts = %u", m_cRetryAttempts);
  2163. StateTrace((LPARAM)this, "m_cRetryMinutes = %u", m_cRetryMinutes);
  2164. dwTempVar = ReadMetabaseDword(mb, MD_REMOTE_RETRY_ATTEMPTS, 48);
  2165. dwTempVar2 = ReadMetabaseDword(mb, MD_REMOTE_RETRY_MINUTES, 60);
  2166. if ( fShowEvents && ((m_cRemoteRetryAttempts != dwTempVar) ||(m_cRemoteRetryMinutes != dwTempVar2))) {
  2167. _itoa(dwTempVar, ScratchBuffer, 10);
  2168. _itoa(dwTempVar2, ScratchBuffer2, 10);
  2169. apszSubStrings[0] = pchAddr1;
  2170. apszSubStrings[1] = "Remote";
  2171. apszSubStrings[2] = ScratchBuffer;
  2172. apszSubStrings[3] = ScratchBuffer2;
  2173. SmtpLogEvent(SMTP_EVENT_SET_RETRY_PARAMETERS, 4, apszSubStrings, 0);
  2174. }
  2175. m_cRemoteRetryAttempts = dwTempVar;
  2176. m_cRemoteRetryMinutes = dwTempVar2;
  2177. StateTrace((LPARAM)this, "m_cRetryAttempts = %u", m_cRemoteRetryAttempts);
  2178. StateTrace((LPARAM)this, "m_cRetryMinutes = %u", m_cRemoteRetryMinutes);
  2179. TempString.Reset();
  2180. m_cbProgressiveRetryMinutes = sizeof(m_szProgressiveRetryMinutes);
  2181. if (mb.GetStr("", MD_SMTP_REMOTE_PROGRESSIVE_RETRY_MINUTES, IIS_MD_UT_SERVER, &TempString, METADATA_INHERIT, "")) {
  2182. lstrcpy(m_szProgressiveRetryMinutes, TempString.QueryStr());
  2183. m_cbProgressiveRetryMinutes = lstrlen(m_szProgressiveRetryMinutes) + 1;
  2184. StateTrace((LPARAM)this, "Progressive retry minutes: <%s>, length %u",
  2185. m_szProgressiveRetryMinutes,
  2186. m_cbProgressiveRetryMinutes);
  2187. }
  2188. //Parse out the string to get at most 4 seperate minute values
  2189. //the values will be part of a comma delimited string
  2190. int cRetryMin[4];
  2191. DWORD i = 0;
  2192. char *szTemp;
  2193. char *Ptr = NULL;
  2194. szTemp = m_szProgressiveRetryMinutes;
  2195. //Parse out the 4 integers
  2196. for (;i<4;) {
  2197. Ptr = strchr(szTemp,',');
  2198. if (Ptr)
  2199. *Ptr = '\0';
  2200. cRetryMin[i] = 0;
  2201. cRetryMin[i] = atoi(szTemp);
  2202. if (cRetryMin[i] < 1)
  2203. break;
  2204. i++;
  2205. if (Ptr) {
  2206. *Ptr = ',';
  2207. szTemp = ++Ptr;
  2208. Ptr = NULL;
  2209. } else
  2210. break;
  2211. }
  2212. //check if could parse nothing
  2213. if (i==0) {
  2214. //dwRetryMin[i] = 60; //defualt retry is 60 minutes
  2215. //NK** for now look at the old value - this way we can set something
  2216. //using MMC
  2217. cRetryMin[i] = m_cRemoteRetryMinutes;
  2218. i++;
  2219. }
  2220. //If not all four retry intervals were specified
  2221. //Make the use the last specifed interval in place of unspecified intervals
  2222. while (i<4) {
  2223. cRetryMin[i] = cRetryMin[i - 1];
  2224. i++;
  2225. }
  2226. AQConfig.dwFirstRetrySeconds = cRetryMin[0] * 60;
  2227. AQConfig.dwSecondRetrySeconds = cRetryMin[1] * 60;
  2228. AQConfig.dwThirdRetrySeconds = cRetryMin[2] * 60;
  2229. AQConfig.dwFourthRetrySeconds = cRetryMin[3] * 60;
  2230. AQConfig.dwConnectionRetryMilliseconds = (m_cRemoteRetryMinutes*60*1000);
  2231. AQConfig.dwRetryThreshold = ReadMetabaseDword(mb,MD_SMTP_REMOTE_RETRY_THRESHOLD,3);
  2232. if (!AQConfig.dwRetryThreshold)
  2233. AQConfig.dwRetryThreshold = 3;
  2234. StateTrace((LPARAM)this, "RetryThreshold = %u", AQConfig.dwRetryThreshold);
  2235. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_CON_RETRY;
  2236. //
  2237. // If DSN intervals are not set, then derive them from the retry intervals
  2238. // 10/6/98 - MikeSwa
  2239. //
  2240. AQConfig.dwDelayExpireMinutes = ReadMetabaseDword(mb,
  2241. MD_SMTP_EXPIRE_REMOTE_DELAY_MIN, m_cRemoteRetryMinutes);
  2242. AQConfig.dwNDRExpireMinutes = ReadMetabaseDword(mb,
  2243. MD_SMTP_EXPIRE_REMOTE_NDR_MIN,
  2244. m_cRemoteRetryMinutes * m_cRemoteRetryAttempts);
  2245. AQConfig.dwAQConfigInfoFlags |=
  2246. (AQ_CONFIG_INFO_EXPIRE_DELAY |
  2247. AQ_CONFIG_INFO_EXPIRE_NDR);
  2248. AQConfig.dwLocalDelayExpireMinutes = ReadMetabaseDword(mb,
  2249. MD_SMTP_EXPIRE_LOCAL_DELAY_MIN, m_cRetryMinutes);
  2250. AQConfig.dwLocalNDRExpireMinutes = ReadMetabaseDword(mb,
  2251. MD_SMTP_EXPIRE_LOCAL_NDR_MIN,
  2252. m_cRetryMinutes * m_cRetryAttempts);
  2253. AQConfig.dwAQConfigInfoFlags |=
  2254. (AQ_CONFIG_INFO_LOCAL_EXPIRE_DELAY |
  2255. AQ_CONFIG_INFO_LOCAL_EXPIRE_NDR);
  2256. }
  2257. if (IsFieldSet(fc, FC_SMTP_INFO_PIPELINE)) {
  2258. dwTempVar = !!ReadMetabaseDword(mb, MD_SHOULD_PIPELINE_OUT, TRUE);
  2259. if (fShowEvents && ((dwTempVar && !m_fShouldPipelineOut) || (!dwTempVar && m_fShouldPipelineOut))) {
  2260. apszSubStrings[0] = pchAddr1;
  2261. if (dwTempVar)
  2262. SmtpLogEvent(SMTP_EVENT_SET_PIPELINE_OUT_ENABLED, 1, apszSubStrings, 0);
  2263. else
  2264. SmtpLogEvent(SMTP_EVENT_SET_PIPELINE_OUT_DISABLED, 1, apszSubStrings, 0);
  2265. }
  2266. m_fShouldPipelineOut = dwTempVar;
  2267. StateTrace((LPARAM)this, "m_fShouldPipelineOut = %u", m_fShouldPipelineOut);
  2268. dwTempVar = !!ReadMetabaseDword(mb, MD_SHOULD_PIPELINE_IN, TRUE);
  2269. if (fShowEvents && ((dwTempVar && !m_fShouldPipelineIn)|| (!dwTempVar && m_fShouldPipelineIn))) {
  2270. apszSubStrings[0] = pchAddr1;
  2271. if (dwTempVar)
  2272. SmtpLogEvent(SMTP_EVENT_SET_PIPELINE_IN_ENABLED, 1, apszSubStrings, 0);
  2273. else
  2274. SmtpLogEvent(SMTP_EVENT_SET_PIPELINE_IN_DISABLED, 1, apszSubStrings, 0);
  2275. }
  2276. m_fShouldPipelineIn = dwTempVar;
  2277. StateTrace((LPARAM)this, "m_fShouldPipelineIn = %u", m_fShouldPipelineIn);
  2278. }
  2279. if (IsFieldSet(fc, FC_SMTP_INFO_SMART_HOST)) {
  2280. dwTempVar = ReadMetabaseDword(mb, MD_SMARTHOST_TYPE, 0);
  2281. StateTrace((LPARAM)this, "m_fSmartHostType = %u", dwTempVar);
  2282. if (dwTempVar != smarthostNone) {
  2283. TempString.Reset();
  2284. if (! mb.GetStr("", MD_SMARTHOST_NAME, IIS_MD_UT_SERVER, &TempString) ||
  2285. TempString.IsEmpty()) {
  2286. // Don't have a smart host, so turn off smart host and start.
  2287. // Log it though, because the settings conflicted and so somebody
  2288. // probably messed up...
  2289. dwTempVar = m_fSmartHostType = smarthostNone;
  2290. m_szSmartHostName[0] = '\0';
  2291. ErrorTrace((LPARAM)this, "Unable to read smart host name, error %u", dwErr);
  2292. apszSubStrings[0] = pchAddr1;
  2293. SmtpLogEvent(SMTP_EVENT_INVALID_SMART_HOST, 1, apszSubStrings, 0);
  2294. } else {
  2295. if (fShowEvents && lstrcmpi(m_szSmartHostName,TempString.QueryStr())) {
  2296. apszSubStrings[0] = pchAddr1;
  2297. apszSubStrings[1] = TempString.QueryStr();
  2298. SmtpLogEvent(SMTP_EVENT_SET_SMART_HOST_NAME, 2, apszSubStrings, 0);
  2299. }
  2300. lstrcpyn (m_szSmartHostName,TempString.QueryStr(), MAX_PATH);
  2301. }
  2302. StateTrace((LPARAM)this, "m_szSmartHost = %s", m_szSmartHostName);
  2303. }
  2304. // If the value is changing, generate an information NT event...
  2305. if (fShowEvents && (dwTempVar != m_fSmartHostType)) {
  2306. apszSubStrings[0] = pchAddr1;
  2307. apszSubStrings[1] = m_szSmartHostName;
  2308. switch (dwTempVar) {
  2309. case smarthostNone:
  2310. {
  2311. SmtpLogEvent(SMTP_EVENT_SET_SMART_HOST_TYPE_NONE, 1, apszSubStrings, 0);
  2312. break;
  2313. }
  2314. case smarthostAfterFail:
  2315. {
  2316. SmtpLogEvent(SMTP_EVENT_SET_SMART_HOST_TYPE_AFTER_FAIL,
  2317. 2, apszSubStrings, 0);
  2318. break;
  2319. }
  2320. case smarthostAlways:
  2321. {
  2322. SmtpLogEvent(SMTP_EVENT_SET_SMART_HOST_TYPE_ALWAYS,
  2323. 2, apszSubStrings, 0);
  2324. break;
  2325. }
  2326. }//end switch
  2327. }//endf if
  2328. m_fSmartHostType = dwTempVar;
  2329. }
  2330. if (IsFieldSet(fc, FC_SMTP_INFO_MASQUERADE)) {
  2331. m_fMasquerade = !!ReadMetabaseDword(mb, MD_DO_MASQUERADE, FALSE);
  2332. StateTrace((LPARAM)this, "m_fSmartHostType = %u", m_fMasquerade);
  2333. if (m_fMasquerade) {
  2334. TempString.Reset();
  2335. if (! mb.GetStr("", MD_MASQUERADE_NAME, IIS_MD_UT_SERVER, &TempString) ||
  2336. TempString.IsEmpty()) {
  2337. // Don't have a masquerade, so turn off masquerading and start.
  2338. // Log it though, because the settings conflicted and so somebody
  2339. // probably messed up...
  2340. m_fMasquerade = 0;
  2341. m_szMasqueradeName[0] = '\0';
  2342. ErrorTrace((LPARAM)this, "Unable to read masquerade name, error %u", dwErr);
  2343. apszSubStrings[0] = pchAddr1;
  2344. SmtpLogEvent(SMTP_EVENT_INVALID_MASQUERADE, 1, apszSubStrings, 0);
  2345. } else {
  2346. if (fShowEvents && lstrcmpi(m_szMasqueradeName,TempString.QueryStr())) {
  2347. apszSubStrings[0] = pchAddr1;
  2348. apszSubStrings[1] = TempString.QueryStr();
  2349. SmtpLogEvent(SMTP_EVENT_SET_MASQUERADE_NAME, 2, apszSubStrings, 0);
  2350. }
  2351. lstrcpyn (m_szMasqueradeName,TempString.QueryStr(), AB_MAX_DOMAIN);
  2352. }
  2353. StateTrace((LPARAM)this, "m_szMasqueradeName = %s", m_szMasqueradeName);
  2354. }
  2355. }
  2356. if (IsFieldSet(fc, FC_SMTP_INFO_DEFAULT_DOMAIN)) {
  2357. m_fDefaultDomainExists = TRUE;
  2358. TempString.Reset();
  2359. if (! mb.GetStr("", MD_DEFAULT_DOMAIN_VALUE, IIS_MD_UT_SERVER, &TempString)) {
  2360. //
  2361. // we set this value on system start up this is a problem... it should be set.
  2362. //
  2363. lstrcpyn(m_szDefaultDomain, ((SMTP_IIS_SERVICE *) g_pInetSvc)->QueryTcpipName() , MAX_PATH);
  2364. ErrorTrace((LPARAM) this, "Error reading Default Domain from Metabase. Using TcpipValue Name: %s", m_szDefaultDomain);
  2365. }
  2366. else if (TempString.IsEmpty()) {
  2367. //
  2368. // blow away the value, this will invoke the routine again, and it will be updated
  2369. // with the higher level default. Just in case, put the Instance value in there as a
  2370. // placeholder... just in case.
  2371. //
  2372. lstrcpyn(m_szDefaultDomain, ((SMTP_IIS_SERVICE *) g_pInetSvc)->QueryTcpipName() , MAX_PATH);
  2373. ErrorTrace((LPARAM) this, "Default Domain was blank string, removing Instance value.");
  2374. if (! mb.DeleteData("", MD_DEFAULT_DOMAIN_VALUE, IIS_MD_UT_SERVER, STRING_METADATA)) {
  2375. ErrorTrace((LPARAM) this, "Error deleting Default Domain from Metabase. Using TcpipValue Name: %s", m_szDefaultDomain);
  2376. }
  2377. }
  2378. else {
  2379. lstrcpyn(m_szDefaultDomain,TempString.QueryStr(), sizeof(m_szDefaultDomain));
  2380. if (fShowEvents) {
  2381. apszSubStrings[0] = pchAddr1;
  2382. apszSubStrings[1] = m_szDefaultDomain;
  2383. // If the value is changing, generate an information NT event...
  2384. SmtpLogEvent(SMTP_EVENT_SET_DEFAULT_DOMAIN, 2, apszSubStrings, 0);
  2385. }
  2386. }
  2387. //
  2388. // Inform aqueue of the default domain
  2389. //
  2390. AQConfig.szDefaultLocalDomain = m_szDefaultDomain;
  2391. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_DEFAULT_DOMAIN;
  2392. ErrorTrace((LPARAM)this , "Default domain is %s", m_szDefaultDomain);
  2393. }
  2394. if (IsFieldSet(fc, FC_SMTP_INFO_FQDN)) {
  2395. TempString.Reset();
  2396. if (! mb.GetStr("", MD_FQDN_VALUE, IIS_MD_UT_SERVER, &TempString)) {
  2397. //
  2398. // We set this value on system start up - see main.cxx,
  2399. // InitializeService
  2400. // This is a problem... it should be set.
  2401. //
  2402. lstrcpyn(m_szFQDomainName, ((SMTP_IIS_SERVICE *) g_pInetSvc)->QueryTcpipName(), MAX_PATH);
  2403. ErrorTrace((LPARAM) this, "Error reading FQDN value from Metabase. Using TcpipValue Name: %s", m_szFQDomainName);
  2404. } else if (TempString.IsEmpty()) {
  2405. //
  2406. // blow away the value, this will invoke the routine again, and it will be updated
  2407. // with the higher level default. Just in case, put the Instance value in there as a
  2408. // placeholder... just in case.
  2409. //
  2410. lstrcpyn(m_szFQDomainName, ((SMTP_IIS_SERVICE *) g_pInetSvc)->QueryTcpipName() , MAX_PATH);
  2411. ErrorTrace((LPARAM) this, "FQDN Value was blank string, removing Instance value.");
  2412. if (! mb.DeleteData("", MD_FQDN_VALUE, IIS_MD_UT_SERVER, STRING_METADATA)) {
  2413. ErrorTrace((LPARAM) this, "Error reading FQDN value from Metabase. Using TcpipValue Name: %s", m_szFQDomainName);
  2414. }
  2415. }
  2416. else {
  2417. lstrcpyn(m_szFQDomainName,TempString.QueryStr(),
  2418. sizeof(m_szFQDomainName));
  2419. //
  2420. // Register the SPNs for this virtual server. Currently, we ignore
  2421. // errors here.
  2422. //
  2423. if (!RegisterServicePrincipalNames(FALSE)) {
  2424. ErrorTrace((LPARAM) this, "Unable to register Kerberos SPNs %d, will try later",
  2425. GetLastError());
  2426. }
  2427. }
  2428. //VerifyFQDNWithBindings();
  2429. AQConfig.szServerFQDN = m_szFQDomainName;
  2430. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_SERVER_FQDN;
  2431. ErrorTrace((LPARAM)this , "Fully qualified domain name is %s", m_szFQDomainName);
  2432. }
  2433. if (IsFieldSet(fc, FC_SMTP_INFO_SEND_TO_ADMIN)) {
  2434. char * DomainOffset = NULL;
  2435. DWORD NameSize = 0;
  2436. TempString.Reset();
  2437. if (! mb.GetStr("", MD_SEND_NDR_TO, IIS_MD_UT_SERVER, &TempString) ||
  2438. TempString.IsEmpty()) {
  2439. m_fSendNDRToAdmin = FALSE;
  2440. m_AdminName[0] = '\0';
  2441. ErrorTrace((LPARAM)this, "Unable to read admin name, error %u", dwErr);
  2442. } else {
  2443. lstrcpyn (m_AdminName,TempString.QueryStr(), MAX_INTERNET_NAME);
  2444. DomainOffset = strchr(m_AdminName, '@');
  2445. if (CAddr::ValidateCleanEmailName(m_AdminName, DomainOffset)) {
  2446. m_fSendNDRToAdmin = TRUE;
  2447. if (DomainOffset == NULL) {
  2448. lstrcat(m_AdminName, "@");
  2449. lstrcat(m_AdminName, m_szDefaultDomain);
  2450. }
  2451. } else {
  2452. ErrorTrace((LPARAM)this, "Unable to read admin name, error %u", dwErr);
  2453. m_AdminName[0] = '\0';
  2454. m_fSendNDRToAdmin = FALSE;
  2455. }
  2456. }
  2457. StateTrace((LPARAM)this, "m_AdminName = %s", m_AdminName);
  2458. if (fShowEvents && m_fSendNDRToAdmin) {
  2459. apszSubStrings[0] = pchAddr1;
  2460. apszSubStrings[1] = m_AdminName;
  2461. SmtpLogEvent(SMTP_EVENT_SET_SEND_NDR_TO_ADMIN_ENABLED, 2, apszSubStrings, 0);
  2462. } else if (fShowEvents && !m_fSendNDRToAdmin) {
  2463. apszSubStrings[0] = pchAddr1;
  2464. SmtpLogEvent(SMTP_EVENT_SET_SEND_NDR_TO_ADMIN_DISABLED, 1, apszSubStrings, 0);
  2465. }
  2466. DomainOffset = NULL;
  2467. NameSize = 0;
  2468. TempString.Reset();
  2469. if (! mb.GetStr("", MD_SEND_BAD_TO, IIS_MD_UT_SERVER, &TempString) ||
  2470. TempString.IsEmpty()) {
  2471. m_fSendBadToAdmin = FALSE;
  2472. m_BadMailName[0] = '\0';
  2473. ErrorTrace((LPARAM)this, "Unable to read badmail email name, error %u", dwErr);
  2474. } else {
  2475. lstrcpyn(m_BadMailName,TempString.QueryStr(), MAX_INTERNET_NAME);
  2476. DomainOffset = strchr(m_BadMailName, '@');
  2477. if (CAddr::ValidateCleanEmailName(m_BadMailName, DomainOffset)) {
  2478. m_fSendBadToAdmin = TRUE;
  2479. if (DomainOffset == NULL) {
  2480. lstrcat(m_BadMailName, "@");
  2481. lstrcat(m_BadMailName, m_szDefaultDomain);
  2482. }
  2483. } else {
  2484. m_fSendBadToAdmin = FALSE;
  2485. m_BadMailName[0] = '\0';
  2486. ErrorTrace((LPARAM)this, "Unable to read badmail email name, error %u", dwErr);
  2487. }
  2488. }
  2489. StateTrace((LPARAM)this, "m_BadMailName = %s", m_BadMailName);
  2490. if (fShowEvents && m_fSendBadToAdmin) {
  2491. apszSubStrings[0] = pchAddr1;
  2492. apszSubStrings[1] = m_BadMailName;
  2493. SmtpLogEvent(SMTP_EVENT_SET_SEND_BAD_TO_ADMIN_ENABLED, 2, apszSubStrings, 0);
  2494. } else if (fShowEvents && !m_fSendBadToAdmin) {
  2495. apszSubStrings[0] = pchAddr1;
  2496. SmtpLogEvent(SMTP_EVENT_SET_SEND_BAD_TO_ADMIN_DISABLED, 1, apszSubStrings, 0);
  2497. }
  2498. }
  2499. if (IsFieldSet(fc, FC_SMTP_INFO_DEFAULT_DROP_DIR)) {
  2500. TempString.Reset();
  2501. if (! mb.GetStr("", MD_MAIL_DROP_DIR, IIS_MD_UT_SERVER, &TempString, 0) ||
  2502. TempString.IsEmpty()) {
  2503. // We had a problem reading the metabase.
  2504. // This is a very bad thing.
  2505. m_szMailDropDir[0] = '\0';
  2506. m_cchMailDropDir = 0;
  2507. apszSubStrings[0] = pchAddr1;
  2508. apszSubStrings[1] = szMailDropDir;
  2509. SmtpLogEvent(SMTP_EVENT_INVALID_MAIL_DROP_DIR, 2, apszSubStrings, 0);
  2510. } else {
  2511. lstrcpyn(m_szMailDropDir, TempString.QueryStr(), MAX_PATH);
  2512. if (fShowEvents) {
  2513. apszSubStrings[0] = pchAddr1;
  2514. apszSubStrings[1] = m_szMailDropDir;
  2515. SmtpLogEvent(SMTP_EVENT_SET_MAIL_DROP_DIR, 2, apszSubStrings, dwErr);
  2516. }
  2517. // We found a path in the reg, so see if we can use it...
  2518. dwAttr = GetFileAttributes(m_szMailDropDir);
  2519. if (dwAttr == 0xFFFFFFFF) {
  2520. // The path doesn't exist yet, so we'll try to create it.
  2521. if (!CreateLayerDirectory(m_szMailDropDir) && (dwErr = GetLastError()) != ERROR_ALREADY_EXISTS) {
  2522. ErrorTrace((LPARAM)this, "Unable to create mail drop directory (%s)", m_szMailQueueDir);
  2523. apszSubStrings[0] = pchAddr1;
  2524. apszSubStrings[1] = m_szMailDropDir;
  2525. SmtpLogEvent(SMTP_EVENT_INVALID_MAIL_DROP_DIR, 2, apszSubStrings, dwErr);
  2526. m_szMailDropDir[0] = '\0';
  2527. m_cchMailDropDir = 0;
  2528. }
  2529. }
  2530. else {
  2531. if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) {
  2532. // The registry points to a file, so we're outta luck.
  2533. // The directory doesn't exist, and we can't create it.
  2534. // Because this is the queue directory, we're not going
  2535. // to be able to start. Log it so it can be fixed, but
  2536. // set fRet to FALSE so that we shut back down.
  2537. ErrorTrace((LPARAM)this, "Mail drop directory (%s) already exists as a file", m_szMailDropDir);
  2538. apszSubStrings[0] = pchAddr1;
  2539. apszSubStrings[1] = m_szMailDropDir;
  2540. SmtpLogEvent(SMTP_EVENT_INVALID_MAIL_DROP_DIR, 2, apszSubStrings, ERROR_ALREADY_EXISTS);
  2541. m_szMailDropDir[0] = '\0';
  2542. }
  2543. }
  2544. if (m_szMailDropDir[0] != '\0') {
  2545. // Looks like everything is going to be OK, so we add a backslash (if
  2546. // necessary) because it makes things easier later.
  2547. m_cchMailDropDir = lstrlen(m_szMailDropDir);
  2548. if (m_cchMailDropDir > 0 && m_szMailDropDir[m_cchMailDropDir - 1] != '\\') {
  2549. lstrcat(m_szMailDropDir, "\\");
  2550. m_cchMailDropDir++;
  2551. }
  2552. }
  2553. }
  2554. }
  2555. //
  2556. // Added by keithlau on 7/8/96
  2557. //
  2558. if (IsFieldSet(fc, FC_SMTP_INFO_BAD_MAIL_DIR)) {
  2559. TempString.Reset();
  2560. if (! mb.GetStr("", MD_BAD_MAIL_DIR, IIS_MD_UT_SERVER, &TempString, 0) ||
  2561. TempString.IsEmpty()) {
  2562. // We had a problem reading the registry, so
  2563. // set the flags back to not save bad mail and
  2564. // log it and hop out.
  2565. // This is NOT fatal. We'll still start up and run,
  2566. // but we're not going to save bad mail, and we wanted
  2567. // to, so at least we'll log the event.
  2568. m_szBadMailDir[0] = '\0';
  2569. ErrorTrace((LPARAM)this, "Unable to read bad mail dir value, error = %u", dwErr);
  2570. apszSubStrings[0] = pchAddr1;
  2571. apszSubStrings[1] = szBadMailDir;
  2572. SmtpLogEvent(SMTP_EVENT_CANNOT_READ_SVC_REGKEY, 2, apszSubStrings, 0);
  2573. } else {
  2574. lstrcpyn (m_szBadMailDir,TempString.QueryStr(), MAX_PATH);
  2575. }
  2576. if (m_szBadMailDir[0] != '\0') {
  2577. // We found a path in the registry, so see if it already exists.
  2578. dwAttr = GetFileAttributes(m_szBadMailDir);
  2579. if (dwAttr == 0xFFFFFFFF) {
  2580. // It doesn't exist at all, so try to create it.
  2581. if (!CreateLayerDirectory(m_szBadMailDir) && (dwErr = GetLastError()) != ERROR_ALREADY_EXISTS) {
  2582. // We couldn't create it, so we can't save bad mail.
  2583. // Log it because somebody messed up the registry.
  2584. // This is NOT fatal. We'll still start up and run,
  2585. // but we're not going to save bad mail, and we wanted
  2586. // to, so at least we'll log the event.
  2587. ErrorTrace((LPARAM)this, "Unable to create bad mail directory (%s)", m_szBadMailDir);
  2588. apszSubStrings[0] = pchAddr1;
  2589. apszSubStrings[1] = m_szBadMailDir;
  2590. SmtpLogEvent(SMTP_EVENT_INVALID_BAD_MAIL_DIR, 2, apszSubStrings, 0);
  2591. m_szBadMailDir[0] = '\0';
  2592. }
  2593. } else {
  2594. if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) {
  2595. // The registry points to a file, so we're outta luck.
  2596. // The directory doesn't exist, and we can't create it.
  2597. // This is NOT fatal. We'll still start up and run,
  2598. // but we're not going to save bad mail, and we wanted
  2599. // to, so at least we'll log the event.
  2600. ErrorTrace((LPARAM)this, "Bad mail directory (%s) already exists", m_szBadMailDir);
  2601. apszSubStrings[0] = pchAddr1;
  2602. apszSubStrings[1] = m_szBadMailDir;
  2603. SmtpLogEvent(SMTP_EVENT_INVALID_BAD_MAIL_DIR, 2, apszSubStrings, 0);
  2604. m_szBadMailDir[0] = '\0';
  2605. }
  2606. }
  2607. StateTrace((LPARAM)this, "Save bad mail is enabled and m_szBadMailDir = %s", m_szBadMailDir);
  2608. } else {
  2609. // We at least leave a trace saying that save bad mail is disabled
  2610. StateTrace((LPARAM)this, "Save bad mail is disabled");
  2611. }
  2612. if (m_szBadMailDir[0] != '\0') {
  2613. // Finally, if everything has gone OK, then add a trailing backslash so
  2614. // that things are easier later.
  2615. dwLen = lstrlen(m_szBadMailDir);
  2616. if (dwLen > 0 && m_szBadMailDir[dwLen-1] != '\\')
  2617. lstrcat(m_szBadMailDir, "\\");
  2618. }
  2619. }
  2620. if (IsFieldSet(fc, FC_SMTP_INFO_DOMAIN_ROUTING)) {
  2621. m_DefaultRouteAction = ReadMetabaseDword(mb, MD_ROUTE_ACTION, 0);
  2622. TempString.Reset();
  2623. if (!mb.GetStr("", MD_ROUTE_USER_NAME, IIS_MD_UT_SERVER, &TempString, 0) ||
  2624. TempString.IsEmpty()) {
  2625. m_DefaultRemoteUserName[0] = '\0';
  2626. m_DefaultRemotePassword[0] = '\0';
  2627. m_DefaultRouteAction &= ~SMTP_AUTH_NTLM;
  2628. m_DefaultRouteAction &= ~SMTP_AUTH_CLEARTEXT;
  2629. m_DefaultRouteAction &= ~SMTP_AUTH_KERBEROS;
  2630. m_DefaultRouteAction &= ~SMTP_SASL;
  2631. } else {
  2632. lstrcpyn (m_DefaultRemoteUserName,TempString.QueryStr(), MAX_INTERNET_NAME);
  2633. }
  2634. TempString.Reset();
  2635. if (!mb.GetStr("", MD_ROUTE_PASSWORD, IIS_MD_UT_SERVER, &TempString, METADATA_SECURE) ||
  2636. TempString.IsEmpty()) {
  2637. m_DefaultRemotePassword[0] = '\0';
  2638. } else {
  2639. lstrcpyn (m_DefaultRemotePassword,TempString.QueryStr(), MAX_PATH);
  2640. }
  2641. // Get change domain name.
  2642. if (m_pChangeObject)
  2643. {
  2644. char *psz = strstr((const char *) m_pChangeObject->pszMDPath, "/Domain/");
  2645. if (!psz)
  2646. {
  2647. // Changing default config or even more, rebuild
  2648. fRebuild = TRUE;
  2649. }
  2650. else
  2651. {
  2652. // Found a normal domain change, copy the name
  2653. strncpy(szDomainName, psz+8, strlen(psz)-8);
  2654. szDomainName[strlen(psz)-8-1]='\0';
  2655. }
  2656. if (!strcmp(szDomainName, "*"))
  2657. {
  2658. // Changing '*' domain, rebuild
  2659. fRebuild = TRUE;
  2660. }
  2661. }
  2662. fRet = GetRouteDomains(mb, szDomainName, fRebuild);
  2663. }
  2664. AQConfig.cbVersion = sizeof(AQConfigInfo);
  2665. //Send badmail information
  2666. AQConfig.szBadMailDir = m_szBadMailDir;
  2667. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_BADMAIL_DIR;
  2668. //Get DSN Options
  2669. AQConfig.dwDSNOptions = ReadMetabaseDword(mb, MD_SMTP_DSN_OPTIONS, DSN_OPTIONS_DEFAULT);
  2670. AQConfig.dwDSNLanguageID = ReadMetabaseDword(mb, MD_SMTP_DSN_LANGUAGE_ID, 0);
  2671. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_USE_DSN_OPTIONS |
  2672. AQ_CONFIG_INFO_USE_DSN_LANGUAGE;
  2673. if (m_fSendNDRToAdmin)
  2674. AQConfig.szSendCopyOfNDRToAddress = m_AdminName;
  2675. else
  2676. AQConfig.szSendCopyOfNDRToAddress = NULL;
  2677. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_SEND_DSN_TO;
  2678. m_pIAdvQueueConfig->SetConfigInfo(&AQConfig);
  2679. //
  2680. // jstamerj 1998/11/17 16:34:48:
  2681. // Set the well known proeprties of ISession
  2682. //
  2683. hr = HrSetWellKnownIServerProps();
  2684. if(FAILED(hr)) {
  2685. //
  2686. // Just like everything else in this fucntion, don't treat
  2687. // this as fatal; just log it
  2688. //
  2689. ErrorTrace((LPARAM)this, "HrSetWellKnownIServerProps failed hr %08lx", hr);
  2690. }
  2691. m_GenLock.ExclusiveUnlock();
  2692. if (!fRet && (GetLastError() == NO_ERROR))
  2693. SetLastError(ERROR_PATH_NOT_FOUND);
  2694. TraceFunctLeaveEx((LPARAM)this);
  2695. return fRet;
  2696. }
  2697. //+---------------------------------------------------------------
  2698. //
  2699. // Function: DeleteDomainEntry
  2700. //
  2701. // Synopsis: Delete a domain from cached tables.
  2702. //
  2703. // Arguments: DomainName: name of the domain to delete.
  2704. //
  2705. // Returns: BOOL - TRUE on SUCCESS, FALSE on FAIL
  2706. //
  2707. //----------------------------------------------------------------
  2708. BOOL SMTP_SERVER_INSTANCE::DeleteDomainEntry(const char *DomainName)
  2709. {
  2710. TraceFunctEnterEx((LPARAM)this, "DeleteDomainEntry");
  2711. DebugTrace((LPARAM)this , "Delete Domain [%s] ", DomainName);
  2712. // Remove this domain from our SMTPSVC tables
  2713. m_TurnAccessList.RemoveFromTable((const char *) DomainName);
  2714. TraceFunctLeaveEx((LPARAM)this);
  2715. return TRUE;
  2716. }
  2717. //+---------------------------------------------------------------
  2718. //
  2719. // Function: RemoveRegParams
  2720. //
  2721. // Synopsis: Remove metabase info from cached tables.
  2722. // We only handle domain removal at this moment.
  2723. //
  2724. // Arguments: DomainName: name of the domain to delete.
  2725. // If DomainName is NULL, we get it from
  2726. // m_pChangeObject.
  2727. //
  2728. // Returns: BOOL - TRUE on SUCCESS, FALSE on FAIL
  2729. //
  2730. //----------------------------------------------------------------
  2731. BOOL SMTP_SERVER_INSTANCE::RemoveRegParams(const char *DomainName)
  2732. {
  2733. TraceFunctEnterEx((LPARAM)this, "RemoveRegParams");
  2734. char szDomainName [AB_MAX_DOMAIN + 1] = {0};
  2735. BOOL fRet = TRUE;
  2736. m_GenLock.ExclusiveLock();
  2737. if (!m_pChangeObject)
  2738. goto Exit;
  2739. if (DomainName)
  2740. {
  2741. strcpy(szDomainName, DomainName);
  2742. }
  2743. else
  2744. {
  2745. // At this stage, we only handle Domain removale.
  2746. char *psz = strstr((const char *) m_pChangeObject->pszMDPath, "/Domain/");
  2747. if (psz)
  2748. {
  2749. // We find it.
  2750. strncpy(szDomainName, psz+8, strlen(psz)-8);
  2751. szDomainName[strlen(psz)-8-1]='\0';
  2752. }
  2753. }
  2754. if (szDomainName[0] == '\0')
  2755. goto Exit;
  2756. {
  2757. HRESULT hr = S_OK;
  2758. char szRoutePath [MAX_PATH + 1];
  2759. char szActionType [MAX_PATH + 1];
  2760. char szUserName [MAX_INTERNET_NAME + 1];
  2761. char szEtrnDomain [AB_MAX_DOMAIN + 1];
  2762. char szPassword [MAX_PATH + 1];
  2763. char szTargetName [MAX_PATH + 1];
  2764. DomainInfo DefaultDomainInfo;
  2765. DomainInfo StarDomainInfo;
  2766. MB mb( (IMDCOM*)g_pInetSvc->QueryMDObject() );
  2767. if( !mb.Open( QueryMDPath(), METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE) )
  2768. {
  2769. fRet = FALSE;
  2770. goto Exit;
  2771. }
  2772. if (!strcmp(szDomainName, "*"))
  2773. {
  2774. // Deleting the '*' domain, must rebuild
  2775. fRet = GetRouteDomains(mb, szDomainName, TRUE);
  2776. goto Exit;
  2777. }
  2778. // Delete the domain from the table in SMTPSVC
  2779. DeleteDomainEntry((const char *) szDomainName);
  2780. // Since we have no way to tell AQ to delete this domain apart from
  2781. // doing a full rebuild, we are going to push the defaults to AQ
  2782. // to overwrite the custom settings this domain had before
  2783. // Load up the "default config" : We get this by loading the server
  2784. // default config and then trying to overwrite it with the '*'
  2785. // domain config (if present)
  2786. // REVIEW : Ideally this code would be in DeleteDomainEntry but putting it
  2787. // there hurts us now because we have to call DeleteDomainEntry from
  2788. // SetRouteDomainParameters to clean the tables in SMTPSVC. If we can get
  2789. // rid of those tables, the layout of these functions shoule be reconsidered.
  2790. wsprintf(szRoutePath, "");
  2791. SetRouteDomainParameters(mb,
  2792. szDomainName,
  2793. szRoutePath,
  2794. szActionType,
  2795. szUserName,
  2796. szEtrnDomain,
  2797. szPassword,
  2798. szTargetName,
  2799. &DefaultDomainInfo);
  2800. if (AlwaysUseSmartHost() && m_szSmartHostName[0]) {
  2801. DefaultDomainInfo.dwDomainInfoFlags |= DOMAIN_INFO_REMOTE_SMARTHOST;
  2802. DefaultDomainInfo.szSmartHostDomainName = m_szSmartHostName;
  2803. DefaultDomainInfo.cbSmartHostDomainNameLength = lstrlen(m_szSmartHostName);
  2804. }
  2805. //check if we should always use SSL
  2806. if (GetDefaultRouteAction() & SMTP_SSL) {
  2807. DefaultDomainInfo.dwDomainInfoFlags |= DOMAIN_INFO_USE_SSL;
  2808. }
  2809. // Try to overwrite this with the "*" domain if it exists
  2810. wsprintf(szRoutePath, "/Domain/*");
  2811. SetRouteDomainParameters(mb,
  2812. szDomainName,
  2813. szRoutePath,
  2814. szActionType,
  2815. szUserName,
  2816. szEtrnDomain,
  2817. szPassword,
  2818. szTargetName,
  2819. &StarDomainInfo);
  2820. // If we found the star domain - dwDomainInfoFlags is zero if
  2821. // the domain does not exist in the metabase
  2822. if (StarDomainInfo.dwDomainInfoFlags) {
  2823. hr = m_pIAdvQueueConfig->SetDomainInfo(&StarDomainInfo);
  2824. }
  2825. // else push the default domain info
  2826. else {
  2827. hr = m_pIAdvQueueConfig->SetDomainInfo(&DefaultDomainInfo);
  2828. }
  2829. }
  2830. Exit:
  2831. m_GenLock.ExclusiveUnlock();
  2832. TraceFunctLeaveEx((LPARAM)this);
  2833. return fRet;
  2834. }
  2835. BOOL SMTP_SERVER_INSTANCE::GetCatInfo(MB& mb, AQConfigInfo& AQConfig)
  2836. {
  2837. STR TempString;
  2838. char Password[MAX_PATH];
  2839. char BindType[MAX_PATH];
  2840. char SchemaType[MAX_PATH];
  2841. char Domain[MAX_PATH];
  2842. char UserName[MAX_PATH];
  2843. char Host[MAX_PATH];
  2844. char NamingContext[MAX_PATH];
  2845. char DsType[MAX_PATH];
  2846. Password[0] = '\0';
  2847. BindType[0] = '\0';
  2848. SchemaType[0] = '\0';
  2849. Domain[0] = '\0';
  2850. UserName[0] = '\0';
  2851. Host[0] = '\0';
  2852. NamingContext[0] = '\0';
  2853. DsType [0] = '\0';
  2854. if( mb.GetDword("RoutingSources", MD_SMTP_DS_USE_CAT, IIS_MD_UT_SERVER, &AQConfig.dwMsgCatEnable))
  2855. {
  2856. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_ENABLE;
  2857. _VERIFY(SUCCEEDED(
  2858. m_InstancePropertyBag.PutDWORD(
  2859. PE_ISERVID_DW_CATENABLE,
  2860. AQConfig.dwMsgCatEnable)));
  2861. }
  2862. if( mb.GetDword("RoutingSources", MD_SMTP_DS_FLAGS, IIS_MD_UT_SERVER, &AQConfig.dwMsgCatFlags))
  2863. {
  2864. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_FLAGS;
  2865. _VERIFY(SUCCEEDED(
  2866. m_InstancePropertyBag.PutDWORD(
  2867. PE_ISERVID_DW_CATFLAGS,
  2868. AQConfig.dwMsgCatFlags)));
  2869. }
  2870. if( mb.GetDword("RoutingSources", MD_SMTP_DS_PORT, IIS_MD_UT_SERVER, &AQConfig.dwMsgCatPort))
  2871. {
  2872. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_PORT;
  2873. _VERIFY(SUCCEEDED(
  2874. m_InstancePropertyBag.PutDWORD(
  2875. PE_ISERVID_DW_CATPORT,
  2876. AQConfig.dwMsgCatPort)));
  2877. }
  2878. TempString.Reset();
  2879. if (mb.GetStr("RoutingSources", MD_SMTP_DS_ACCOUNT, IIS_MD_UT_SERVER, &TempString) &&
  2880. !TempString.IsEmpty()) {
  2881. lstrcpyn(UserName, TempString.QueryStr(), MAX_PATH);
  2882. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_USER;
  2883. AQConfig.szMsgCatUser = UserName;
  2884. _VERIFY(SUCCEEDED(
  2885. m_InstancePropertyBag.PutStringA(
  2886. PE_ISERVID_SZ_CATUSER,
  2887. TempString.QueryStr())));
  2888. }
  2889. TempString.Reset();
  2890. if (mb.GetStr("RoutingSources", MD_SMTP_DS_SCHEMA_TYPE, IIS_MD_UT_SERVER, &TempString) &&
  2891. !TempString.IsEmpty()) {
  2892. lstrcpyn(SchemaType, TempString.QueryStr(), MAX_PATH);
  2893. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_SCHEMATYPE;
  2894. AQConfig.szMsgCatSchemaType = SchemaType;
  2895. _VERIFY(SUCCEEDED(
  2896. m_InstancePropertyBag.PutStringA(
  2897. PE_ISERVID_SZ_CATSCHEMA,
  2898. TempString.QueryStr())));
  2899. }
  2900. TempString.Reset();
  2901. if (mb.GetStr("RoutingSources", MD_SMTP_DS_BIND_TYPE, IIS_MD_UT_SERVER, &TempString) &&
  2902. !TempString.IsEmpty()) {
  2903. lstrcpyn(BindType, TempString.QueryStr(), MAX_PATH);
  2904. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_BINDTYPE;
  2905. AQConfig.szMsgCatBindType = BindType;
  2906. _VERIFY(SUCCEEDED(
  2907. m_InstancePropertyBag.PutStringA(
  2908. PE_ISERVID_SZ_CATBINDTYPE,
  2909. TempString.QueryStr())));
  2910. }
  2911. TempString.Reset();
  2912. if (mb.GetStr("RoutingSources", MD_SMTP_DS_PASSWORD, IIS_MD_UT_SERVER, &TempString, METADATA_INHERIT | METADATA_SECURE )) {
  2913. lstrcpyn(Password, TempString.QueryStr(), MAX_PATH);
  2914. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_PASSWORD;
  2915. AQConfig.szMsgCatPassword = Password;
  2916. _VERIFY(SUCCEEDED(
  2917. m_InstancePropertyBag.PutStringA(
  2918. PE_ISERVID_SZ_CATPASSWORD,
  2919. TempString.QueryStr())));
  2920. }
  2921. TempString.Reset();
  2922. if (mb.GetStr("RoutingSources", MD_SMTP_DS_DOMAIN, IIS_MD_UT_SERVER, &TempString) &&
  2923. !TempString.IsEmpty()) {
  2924. lstrcpyn(Domain, TempString.QueryStr(), MAX_PATH);
  2925. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_DOMAIN;
  2926. AQConfig.szMsgCatDomain = Domain;
  2927. _VERIFY(SUCCEEDED(
  2928. m_InstancePropertyBag.PutStringA(
  2929. PE_ISERVID_SZ_CATDOMAIN,
  2930. TempString.QueryStr())));
  2931. }
  2932. TempString.Reset();
  2933. if (mb.GetStr("RoutingSources", MD_SMTP_DS_NAMING_CONTEXT, IIS_MD_UT_SERVER, &TempString) &&
  2934. !TempString.IsEmpty()) {
  2935. lstrcpyn(NamingContext, TempString.QueryStr(), MAX_PATH);
  2936. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_NAMING_CONTEXT;
  2937. AQConfig.szMsgCatNamingContext = NamingContext;
  2938. _VERIFY(SUCCEEDED(
  2939. m_InstancePropertyBag.PutStringA(
  2940. PE_ISERVID_SZ_CATNAMINGCONTEXT,
  2941. TempString.QueryStr())));
  2942. }
  2943. TempString.Reset();
  2944. if (mb.GetStr("RoutingSources", MD_SMTP_DS_TYPE, IIS_MD_UT_SERVER, &TempString) &&
  2945. !TempString.IsEmpty()) {
  2946. lstrcpyn(DsType, TempString.QueryStr(), MAX_PATH);
  2947. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_TYPE;
  2948. AQConfig.szMsgCatType = DsType;
  2949. _VERIFY(SUCCEEDED(
  2950. m_InstancePropertyBag.PutStringA(
  2951. PE_ISERVID_SZ_CATDSTYPE,
  2952. TempString.QueryStr())));
  2953. }
  2954. AQConfig.cbVersion = sizeof(AQConfigInfo);
  2955. TempString.Reset();
  2956. if(mb.GetStr("RoutingSources", MD_SMTP_DS_HOST, IIS_MD_UT_SERVER, &TempString) &&
  2957. !TempString.IsEmpty())
  2958. {
  2959. lstrcpyn(Host, TempString.QueryStr(), MAX_PATH);
  2960. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_HOST;
  2961. AQConfig.szMsgCatHost = Host;
  2962. _VERIFY(SUCCEEDED(
  2963. m_InstancePropertyBag.PutStringA(
  2964. PE_ISERVID_SZ_CATDSHOST,
  2965. TempString.QueryStr())));
  2966. }
  2967. //
  2968. // Indicate that all the official "msgcat" keys that exist are set
  2969. //
  2970. AQConfig.dwAQConfigInfoFlags |= AQ_CONFIG_INFO_MSGCAT_DEFAULT;
  2971. AQConfig.cbVersion = sizeof(AQConfigInfo);
  2972. m_pIAdvQueueConfig->SetConfigInfo(&AQConfig);
  2973. return TRUE;
  2974. }
  2975. BOOL SMTP_SERVER_INSTANCE::ReadRouteDomainIpSecList(MB& mb)
  2976. {
  2977. IMDCOM* pMBCom;
  2978. HRESULT hRes;
  2979. METADATA_RECORD mdRecord;
  2980. DWORD dwRequiredLen;
  2981. DWORD dwErr;
  2982. BOOL fSuccess = TRUE;
  2983. char *szValueName = "";
  2984. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::ReadRouteDomainIpSecList");
  2985. ResetRelayIpSecList();
  2986. pMBCom = (IMDCOM*)m_Service->QueryMDObject();
  2987. mdRecord.dwMDIdentifier = MD_SMTP_IP_RELAY_ADDRESSES;
  2988. mdRecord.dwMDAttributes = METADATA_INHERIT;
  2989. mdRecord.dwMDUserType = IIS_MD_UT_FILE;
  2990. mdRecord.dwMDDataType = BINARY_METADATA;
  2991. mdRecord.dwMDDataLen = 5000;
  2992. mdRecord.pbMDData = (PBYTE) new char [5000];
  2993. if (mdRecord.pbMDData == NULL) {
  2994. TraceFunctLeaveEx((LPARAM)this);
  2995. return FALSE;
  2996. }
  2997. hRes = pMBCom->ComMDGetMetaData( mb.QueryHandle(),
  2998. (LPBYTE)szValueName,
  2999. &mdRecord,
  3000. &dwRequiredLen );
  3001. if ( SUCCEEDED( hRes ) ) {
  3002. SetRelayIpSecList(mdRecord.pbMDData,
  3003. mdRecord.dwMDDataLen,
  3004. mdRecord.dwMDDataTag );
  3005. } else {
  3006. if (mdRecord.pbMDData)
  3007. delete mdRecord.pbMDData;
  3008. fSuccess = FALSE;
  3009. dwErr = HRESULTTOWIN32( hRes );
  3010. }
  3011. TraceFunctLeaveEx((LPARAM)this);
  3012. return fSuccess;
  3013. }
  3014. void SMTP_SERVER_INSTANCE::BuildTurnTable(MULTISZ& msz, char * szDomainName)
  3015. {
  3016. const char * StartPtr = NULL;
  3017. CTurnData * pTurnData = NULL;
  3018. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::BuildTurnTable");
  3019. for (StartPtr = msz.First(); StartPtr != NULL; StartPtr = msz.Next( StartPtr )) {
  3020. ((PSMTP_IIS_SERVICE) g_pInetSvc)->StartHintFunction();
  3021. DebugTrace((LPARAM)this , "%s is allowed to issue TURN", StartPtr);
  3022. pTurnData = new CTurnData(StartPtr, szDomainName);
  3023. if (pTurnData != NULL) {
  3024. if (!m_TurnAccessList.InsertIntoTable((CHASH_ENTRY *) pTurnData)) {
  3025. delete pTurnData;
  3026. }
  3027. }
  3028. }
  3029. TraceFunctLeaveEx((LPARAM)this);
  3030. }
  3031. //+---------------------------------------------------------------
  3032. //
  3033. // Function: SetRouteDomainParameters
  3034. //
  3035. // Synopsis: Does the actual work of adding a domain from the metabase
  3036. //
  3037. //----------------------------------------------------------------
  3038. void SMTP_SERVER_INSTANCE::SetRouteDomainParameters(MB &mb,
  3039. char *szDomainName,
  3040. char *szRoutePath,
  3041. char szActionType [MAX_PATH + 1],
  3042. char szUserName [MAX_INTERNET_NAME + 1],
  3043. char szEtrnDomain [MAX_INTERNET_NAME + 1],
  3044. char szPassword [MAX_PATH + 1],
  3045. char szTargetName [MAX_PATH + 1],
  3046. DomainInfo *pLocalDomainInfo)
  3047. {
  3048. TraceFunctEnter("SMTP_SERVER_INSTANCE::SetRouteDomainParameters");
  3049. char * DomainPtr = NULL;
  3050. char * UserNamePtr = NULL;
  3051. char * PasswordPtr = NULL;
  3052. char * TargetNamePtr = NULL;
  3053. DWORD dwAction = 0;
  3054. STR TempString;
  3055. DWORD dwErr = NO_ERROR;
  3056. DWORD dwLen = 0;
  3057. BOOL RelayForAuth = TRUE;
  3058. DWORD dwEtrnWaitTime = 0;
  3059. BOOL WildCard = FALSE;
  3060. CHAR pchAddr1[32] = "";
  3061. MULTISZ msz;
  3062. if (szDomainName[0]) {
  3063. ZeroMemory(pLocalDomainInfo, sizeof(DomainInfo));
  3064. pLocalDomainInfo->cbVersion = sizeof(DomainInfo);
  3065. pLocalDomainInfo->cbDomainNameLength = lstrlen(szDomainName);
  3066. pLocalDomainInfo->szDomainName = szDomainName;
  3067. szActionType [0] = '\0';
  3068. szUserName [0] = '\0';
  3069. szPassword [0] = '\0';
  3070. szEtrnDomain[0] = '\0';
  3071. szTargetName[0] = '\0';
  3072. UserNamePtr = szUserName;
  3073. PasswordPtr = szPassword;
  3074. TargetNamePtr = szTargetName;
  3075. dwAction = 0;
  3076. DomainPtr = szDomainName;
  3077. if (!mb.GetDword(szRoutePath, MD_ROUTE_ACTION, IIS_MD_UT_SERVER, &dwAction)) {
  3078. dwAction = 0;
  3079. }
  3080. // If we don't recognize the actions we bail now - SMTP_DEFAULT
  3081. // shound never be set on any RouteAction in the metabase
  3082. if ((dwAction & ~SMTP_ALL_ROUTE_FLAGS) || (dwAction & SMTP_DEFAULT)) {
  3083. TraceFunctLeave();
  3084. return;
  3085. }
  3086. TempString.Reset();
  3087. if (mb.GetStr(szRoutePath, MD_ROUTE_ACTION_TYPE, IIS_MD_UT_SERVER, &TempString, 0) &&
  3088. !TempString.IsEmpty()) {
  3089. lstrcpyn(szActionType, TempString.QueryStr(), MAX_PATH);
  3090. }
  3091. TempString.Reset();
  3092. if (((dwAction & SMTP_SMARTHOST) || (dwAction & SMTP_SASL)) && mb.GetStr(szRoutePath, MD_ROUTE_USER_NAME, IIS_MD_UT_SERVER, &TempString) &&
  3093. !TempString.IsEmpty()) {
  3094. lstrcpyn(szUserName, TempString.QueryStr(), MAX_INTERNET_NAME);
  3095. } else {
  3096. UserNamePtr = NULL;
  3097. }
  3098. TempString.Reset();
  3099. if (UserNamePtr != NULL) {
  3100. if (mb.GetStr(szRoutePath, MD_ROUTE_PASSWORD, IIS_MD_UT_SERVER, &TempString, METADATA_SECURE | METADATA_INHERIT) &&
  3101. !TempString.IsEmpty()) {
  3102. lstrcpyn(szPassword, TempString.QueryStr(), MAX_PATH);
  3103. }
  3104. } else {
  3105. PasswordPtr = "";
  3106. }
  3107. TempString.Reset();
  3108. if (TargetNamePtr != NULL) {
  3109. if (mb.GetStr(szRoutePath, MD_ROUTE_AUTHTARGET, IIS_MD_UT_SERVER, &TempString, METADATA_SECURE | METADATA_INHERIT) &&
  3110. !TempString.IsEmpty()) {
  3111. lstrcpyn(szTargetName, TempString.QueryStr(), MAX_PATH);
  3112. }
  3113. } else {
  3114. TargetNamePtr = "";
  3115. }
  3116. TempString.Reset();
  3117. if (mb.GetStr(szRoutePath, MD_SMTP_CSIDE_ETRN_DOMAIN, IIS_MD_UT_SERVER, &TempString, 0) &&
  3118. !TempString.IsEmpty()) {
  3119. lstrcpyn(szEtrnDomain, TempString.QueryStr(), AB_MAX_DOMAIN);
  3120. }
  3121. dwEtrnWaitTime = ReadMetabaseDword(mb, MD_SMTP_CSIDE_ETRN_DELAY, 0);
  3122. //
  3123. // If the domain is set to explicitly allow relay for authenticated users..
  3124. // use that value. Otherwise, use the value set on the VSI (to maintain
  3125. // backwards compatibility with W2K users).
  3126. //
  3127. if (dwAction & SMTP_AUTH_RELAY)
  3128. RelayForAuth = TRUE;
  3129. else
  3130. RelayForAuth = m_fRelayForAuthUsers;
  3131. if (dwAction & SMTP_SMARTHOST) {
  3132. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_REMOTE_SMARTHOST;
  3133. if (dwAction & SMTP_SSL)
  3134. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_USE_SSL;
  3135. if (szActionType[0] != '\0') {
  3136. pLocalDomainInfo->szSmartHostDomainName = szActionType;
  3137. pLocalDomainInfo->cbSmartHostDomainNameLength = lstrlen(szActionType);
  3138. } else if (*szDomainName == '*') {
  3139. //The domain names could be specified as "*" - an explicit smart
  3140. //host must be used.
  3141. pLocalDomainInfo->dwDomainInfoFlags &= ~DOMAIN_INFO_REMOTE_SMARTHOST;
  3142. } else { //use the domain name as our smarthost
  3143. pLocalDomainInfo->szSmartHostDomainName = szDomainName;
  3144. pLocalDomainInfo->cbSmartHostDomainNameLength = lstrlen(pLocalDomainInfo->szSmartHostDomainName);
  3145. }
  3146. }
  3147. //if we are doing SASL, make sure we have a username and password
  3148. //and a correct authentication bits
  3149. if (dwAction & SMTP_SASL) {
  3150. // One of these must be set or else the SMTP_SASL flag doesn't
  3151. // make sense
  3152. if (!(dwAction & SMTP_AUTH_NTLM) &&
  3153. !(dwAction & SMTP_AUTH_CLEARTEXT) &&
  3154. !(dwAction & SMTP_AUTH_KERBEROS)) {
  3155. // dbraun : we can be cleaner about handling this - bailing
  3156. // leaves us with an incompletely configured domain
  3157. TraceFunctLeave();
  3158. return;
  3159. }
  3160. if (UserNamePtr) {
  3161. pLocalDomainInfo->szUserName = UserNamePtr;
  3162. pLocalDomainInfo->cbUserNameLength = lstrlen (UserNamePtr);
  3163. }
  3164. if (PasswordPtr) {
  3165. pLocalDomainInfo->szPassword = PasswordPtr;
  3166. pLocalDomainInfo->cbPasswordLength = lstrlen(PasswordPtr);
  3167. }
  3168. if (dwAction & SMTP_AUTH_NTLM) {
  3169. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_USE_NTLM;
  3170. }
  3171. if (dwAction & SMTP_AUTH_CLEARTEXT) {
  3172. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_USE_PLAINTEXT;
  3173. }
  3174. if (dwAction & SMTP_AUTH_KERBEROS) {
  3175. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_USE_KERBEROS;
  3176. if (TargetNamePtr) {
  3177. pLocalDomainInfo->szAuthType = TargetNamePtr;
  3178. pLocalDomainInfo->cbAuthTypeLength = lstrlen(TargetNamePtr);
  3179. }
  3180. }
  3181. }
  3182. char * szTmpDomain;
  3183. //Check for the wildcard entries
  3184. if (*DomainPtr == '*' && *(DomainPtr+1) == '.') {
  3185. WildCard = TRUE;
  3186. szTmpDomain = DomainPtr + 2;
  3187. } else {
  3188. szTmpDomain = DomainPtr;
  3189. }
  3190. if (szTmpDomain[0] != '*' || szTmpDomain[1] != 0) {
  3191. if (!CAddr::ValidateDomainName(szTmpDomain)) {
  3192. ErrorTrace((LPARAM)this , "%s is an invalid domain", DomainPtr);
  3193. //bad domain name
  3194. TraceFunctLeave();
  3195. return;
  3196. }
  3197. }
  3198. if (dwAction & SMTP_DROP) {
  3199. if (!CreateLayerDirectory(szActionType) && (dwErr = GetLastError()) != ERROR_ALREADY_EXISTS) {
  3200. // Reflect the changes
  3201. const CHAR *aszStrings[3];
  3202. CHAR szTemp1[MAX_PATH + 1];
  3203. CHAR szTemp2[MAX_PATH + 1];
  3204. aszStrings[0] = pchAddr1;
  3205. aszStrings[1] = szTemp1;
  3206. aszStrings[2] = szTemp2;
  3207. lstrcpyn(szTemp1, szActionType, MAX_PATH);
  3208. lstrcpyn(szTemp2, DomainPtr, MAX_PATH);
  3209. SmtpLogEvent(SMTP_EVENT_NO_DROP_DIRECTORY, 3, aszStrings, dwErr);
  3210. }
  3211. dwLen = lstrlen(szActionType);
  3212. if (dwLen > 0 && szActionType[dwLen-1] != '\\')
  3213. lstrcat(szActionType, "\\");
  3214. pLocalDomainInfo->szDropDirectory = szActionType;
  3215. pLocalDomainInfo->cbDropDirectoryLength = lstrlen (szActionType);
  3216. pLocalDomainInfo->dwDomainInfoFlags = DOMAIN_INFO_LOCAL_DROP;
  3217. }
  3218. // Remove original one if it is there
  3219. DeleteDomainEntry((const char *) DomainPtr);
  3220. //
  3221. // Insert local domains into the routing table.
  3222. //
  3223. if ((dwAction & SMTP_DELIVER) && (szActionType[0] == '\0')) {
  3224. DebugTrace((LPARAM)this , "adding %s as a DELIVER domain", szDomainName);
  3225. pLocalDomainInfo->dwDomainInfoFlags = DOMAIN_INFO_LOCAL_MAILBOX;
  3226. } else if (dwAction & SMTP_ALIAS) {
  3227. DebugTrace((LPARAM)this , "adding %s as a ALIAS domain", szDomainName);
  3228. if (IsDefaultInRt()) {
  3229. pLocalDomainInfo->dwDomainInfoFlags = DOMAIN_INFO_LOCAL_MAILBOX | DOMAIN_INFO_ALIAS;
  3230. } else {
  3231. pLocalDomainInfo->szDropDirectory = m_szMailDropDir;
  3232. pLocalDomainInfo->cbDropDirectoryLength = lstrlen (m_szMailDropDir);
  3233. pLocalDomainInfo->dwDomainInfoFlags = DOMAIN_INFO_LOCAL_DROP | DOMAIN_INFO_ALIAS;
  3234. }
  3235. }
  3236. if (RelayForAuth) {
  3237. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_AUTH_RELAY;
  3238. }
  3239. if (dwAction & SMTP_DOMAIN_RELAY) {
  3240. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_DOMAIN_RELAY;
  3241. }
  3242. msz.Reset();
  3243. if ((dwAction & SMTP_ETRN_CMD) && mb.GetMultisz(szRoutePath, MD_SMTP_AUTHORIZED_TURN_LIST, IIS_MD_UT_SERVER, &msz) &&
  3244. !msz.IsEmpty()) {
  3245. BuildTurnTable(msz, szTmpDomain);
  3246. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_TURN_ONLY;
  3247. }
  3248. if (dwAction & SMTP_ETRN_CMD && !(dwAction & SMTP_DISABLE_ETRN) ) {
  3249. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_ETRN_ONLY;
  3250. }//if(dwAction & SMTP_ETRN_CMD)
  3251. if (dwAction & SMTP_USE_HELO ) {
  3252. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_USE_HELO;
  3253. }//if(dwAction & SMTP_USE_HELO)
  3254. if (dwAction & SMTP_CSIDE_ETRN) {
  3255. TempString.Reset();
  3256. if (mb.GetStr(szRoutePath, MD_SMTP_CSIDE_ETRN_DOMAIN, IIS_MD_UT_SERVER, &TempString, 0) &&
  3257. !TempString.IsEmpty()) {
  3258. pLocalDomainInfo->szETRNDomainName = szEtrnDomain;
  3259. lstrcpyn(pLocalDomainInfo->szETRNDomainName, TempString.QueryStr(), AB_MAX_DOMAIN);
  3260. pLocalDomainInfo->cbETRNDomainNameLength = strlen(szEtrnDomain);
  3261. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_SEND_ETRN;
  3262. }
  3263. }//if(dwAction & SMTP_CSIDE_ETRN)
  3264. if (dwAction & SMTP_CSIDE_TURN) {
  3265. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_SEND_TURN;
  3266. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_TURN_ON_EMPTY;
  3267. }//if(dwAction & SMTP_CSIDE_TURN)
  3268. if (dwAction & SMTP_DISABLE_BMIME) {
  3269. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_DISABLE_BMIME;
  3270. }//if(dwAction & SMTP_DISABLE_BMIME)
  3271. if (dwAction & SMTP_CHUNKING) {
  3272. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_USE_CHUNKING;
  3273. }//if(dwAction & SMTP_CHUNKING)
  3274. else if (dwAction & SMTP_DISABLE_CHUNK) {
  3275. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_DISABLE_CHUNKING;
  3276. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_DISABLE_BMIME;
  3277. }
  3278. if (dwAction & SMTP_DISABLE_DSN) {
  3279. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_DISABLE_DSN;
  3280. }//if(dwAction & SMTP_DISBALE_DSN)
  3281. if (dwAction & SMTP_DISABLE_PIPELINE) {
  3282. pLocalDomainInfo->dwDomainInfoFlags |= DOMAIN_INFO_DISABLE_PIPELINE;
  3283. }//if(dwAction & SMTP_DISABLE_PIPELINE)
  3284. }//if (szDomainName[0])
  3285. TraceFunctLeave();
  3286. }
  3287. //+---------------------------------------------------------------
  3288. //
  3289. // Function: AddDomainEntry
  3290. //
  3291. // Synopsis: Add a domain into cached tables.
  3292. //
  3293. // Arguments: MB: already opened metabase.
  3294. // DomainName: name of the domain to add.
  3295. //
  3296. // Returns: BOOL - TRUE on SUCCESS, FALSE on FAIL
  3297. //
  3298. //----------------------------------------------------------------
  3299. BOOL SMTP_SERVER_INSTANCE::AddDomainEntry (MB &mb, char * DomainName)
  3300. {
  3301. HRESULT hr = S_OK;
  3302. BOOL fReturn = TRUE;
  3303. char szDomainName [AB_MAX_DOMAIN + 1];
  3304. char szRoutePath [MAX_PATH + 1];
  3305. char szActionType [MAX_PATH + 1];
  3306. char szUserName [MAX_INTERNET_NAME + 1];
  3307. char szEtrnDomain [AB_MAX_DOMAIN + 1];
  3308. char szPassword [MAX_PATH + 1];
  3309. char szTargetName [MAX_PATH + 1];
  3310. DomainInfo LocalDomainInfo;
  3311. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::AddNewEntry");
  3312. strcpy(szDomainName, DomainName);
  3313. if (szDomainName[0])
  3314. {
  3315. szRoutePath[0] = '\0';
  3316. wsprintf(szRoutePath, "/Domain/%s", szDomainName);
  3317. SetRouteDomainParameters(mb,
  3318. szDomainName,
  3319. szRoutePath,
  3320. szActionType,
  3321. szUserName,
  3322. szEtrnDomain,
  3323. szPassword,
  3324. szTargetName,
  3325. &LocalDomainInfo);
  3326. hr = m_pIAdvQueueConfig->SetDomainInfo(&LocalDomainInfo);
  3327. if (FAILED(hr))
  3328. {
  3329. fReturn = FALSE;
  3330. }
  3331. }//if (szDomainName[0])
  3332. TraceFunctLeaveEx((LPARAM)this);
  3333. return fReturn;
  3334. }
  3335. //+---------------------------------------------------------------
  3336. //
  3337. // Function: GetRouteDomains
  3338. //
  3339. // Synopsis: Get Routing domains from the metabase
  3340. //
  3341. // Arguments: MB: already opened metabase.
  3342. // DomainName: name of the domain to add.
  3343. // fRebuild: bool indicating if we need to rebuild
  3344. // the whole table
  3345. //
  3346. // Returns: BOOL - TRUE on SUCCESS, FALSE on FAIL
  3347. //
  3348. //----------------------------------------------------------------
  3349. BOOL SMTP_SERVER_INSTANCE::GetRouteDomains(MB &mb, char * DomainName, BOOL fRebuild)
  3350. {
  3351. HRESULT hr = S_OK;
  3352. DWORD ThreadId;
  3353. DWORD error;
  3354. BOOL fReturn = TRUE;
  3355. DomainInfo LocalDomainInfo;
  3356. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::GetRouteDomains");
  3357. ((PSMTP_IIS_SERVICE) g_pInetSvc)->StartHintFunction();
  3358. m_TurnAccessList.SetDupesAllowed();
  3359. // Only rebuild when fRebuild is TRUE.
  3360. if (fRebuild)
  3361. {
  3362. // We need to clean m_hEnumDomainThreadHandle here
  3363. // to avoid handle leak.
  3364. if (m_hEnumDomainThreadHandle)
  3365. {
  3366. if (!m_fEnumThreadStarted) {
  3367. // the thread has been created, but it has not been
  3368. // able to grab the gencrit lock yet. This means
  3369. // that it will be doing a full rebuild already, so
  3370. // we can just bail
  3371. goto cleanup;
  3372. }
  3373. // Set up signal and wait
  3374. WaitForSingleObject(m_hEnumDomainThreadHandle, INFINITE);
  3375. ErrorTrace((LPARAM)this, "EnumDomain Thread is dead");
  3376. CloseHandle(m_hEnumDomainThreadHandle);
  3377. m_hEnumDomainThreadHandle = NULL;
  3378. }
  3379. m_fEnumThreadStarted = FALSE;
  3380. m_hEnumDomainThreadHandle = CreateThread (NULL, 0,
  3381. EnumAllDomains, this, 0, &ThreadId);
  3382. if(m_hEnumDomainThreadHandle == NULL)
  3383. {
  3384. error = GetLastError();
  3385. ErrorTrace((LPARAM)this, "CreateThread failed for EnumAllDomains. err: %u", error);
  3386. fReturn = FALSE;
  3387. }
  3388. else
  3389. {
  3390. DebugTrace((LPARAM)this , "EnumDomainThread is created, threadId [%ld]", ThreadId);
  3391. }
  3392. }
  3393. else
  3394. {
  3395. if (!AddDomainEntry(mb, DomainName))
  3396. fReturn = FALSE;
  3397. }
  3398. cleanup:
  3399. TraceFunctLeaveEx((LPARAM)this);
  3400. return fReturn;
  3401. }
  3402. //+---------------------------------------------------------------
  3403. //
  3404. // Function: EnumAllDomains
  3405. //
  3406. // Synopsis: Enumerate all domains in this SMTP instance.
  3407. //
  3408. // Arguments: ptr: pointer to the SMTP server instance.
  3409. //
  3410. // Returns: BOOL - TRUE on SUCCESS, FALSE on FAIL
  3411. //
  3412. //----------------------------------------------------------------
  3413. DWORD EnumAllDomains(VOID *ptr)
  3414. {
  3415. HRESULT hr = S_OK;
  3416. char szDomainName [AB_MAX_DOMAIN + 1];
  3417. char szRoutePath [MAX_PATH + 1];
  3418. char szActionType [MAX_PATH + 1];
  3419. char szUserName [MAX_INTERNET_NAME + 1];
  3420. char szEtrnDomain [AB_MAX_DOMAIN + 1];
  3421. char szPassword [MAX_PATH + 1];
  3422. char szTargetName [MAX_PATH + 1];
  3423. char szStarDomain[] = "*";
  3424. DWORD dwTotal = 0;
  3425. DomainInfo LocalDomainInfo;
  3426. MB mb( (IMDCOM*)g_pInetSvc->QueryMDObject() );
  3427. SMTP_SERVER_INSTANCE *pInstance = (SMTP_SERVER_INSTANCE *) ptr;
  3428. TraceFunctEnterEx((LPARAM)pInstance, "EnumAllDomains");
  3429. pInstance->ExclusiveLockGenCrit();
  3430. pInstance->m_fEnumThreadStarted = TRUE;
  3431. pInstance->m_TurnAccessList.SetDupesAllowed();
  3432. pInstance->m_TurnAccessList.RemoveAllEntries();
  3433. //Signal AQ that we are starting over
  3434. pInstance->m_pIAdvQueueConfig->StartConfigUpdate();
  3435. if (pInstance->m_szMailDropDir[0] == '\0')
  3436. {
  3437. ZeroMemory(&LocalDomainInfo, sizeof(DomainInfo));
  3438. LocalDomainInfo.cbVersion = sizeof(DomainInfo);
  3439. LocalDomainInfo.cbDomainNameLength = lstrlen(pInstance->m_szDefaultDomain);
  3440. LocalDomainInfo.szDomainName = pInstance->m_szDefaultDomain;
  3441. LocalDomainInfo.dwDomainInfoFlags = DOMAIN_INFO_LOCAL_MAILBOX;
  3442. HRESULT hr;
  3443. hr = pInstance->m_pIAdvQueueConfig->SetDomainInfo(&LocalDomainInfo);
  3444. DebugTrace((LPARAM)pInstance , "default domain %s was added to the routing table", pInstance->m_szDefaultDomain);
  3445. //signals default domain was added to routing table
  3446. pInstance->m_fDefaultInRt = TRUE;
  3447. }
  3448. else
  3449. {
  3450. ZeroMemory(&LocalDomainInfo, sizeof(DomainInfo));
  3451. LocalDomainInfo.cbVersion = sizeof(DomainInfo);
  3452. LocalDomainInfo.cbDomainNameLength = lstrlen(pInstance->m_szDefaultDomain);
  3453. LocalDomainInfo.szDomainName = pInstance->m_szDefaultDomain;
  3454. LocalDomainInfo.szDropDirectory = pInstance->m_szMailDropDir;
  3455. LocalDomainInfo.cbDropDirectoryLength = lstrlen (pInstance->m_szMailDropDir);
  3456. LocalDomainInfo.dwDomainInfoFlags = DOMAIN_INFO_LOCAL_DROP;
  3457. hr = pInstance->m_pIAdvQueueConfig->SetDomainInfo(&LocalDomainInfo);
  3458. }
  3459. if( !mb.Open( pInstance->QueryMDPath(), METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE) )
  3460. {
  3461. pInstance->ExclusiveUnLockGenCrit();
  3462. return FALSE;
  3463. }
  3464. while (!pInstance->IsShuttingDown() && mb.EnumObjects("/Domain", szDomainName, dwTotal++)) {
  3465. if (szDomainName[0]) {
  3466. szRoutePath[0] = '\0';
  3467. wsprintf(szRoutePath, "/Domain/%s", szDomainName);
  3468. pInstance->SetRouteDomainParameters(mb,
  3469. szDomainName,
  3470. szRoutePath,
  3471. szActionType,
  3472. szUserName,
  3473. szEtrnDomain,
  3474. szPassword,
  3475. szTargetName,
  3476. &LocalDomainInfo);
  3477. hr = pInstance->m_pIAdvQueueConfig->SetDomainInfo(&LocalDomainInfo);
  3478. if (FAILED(hr)) {
  3479. }
  3480. }//if (szDomainName[0])
  3481. }//while (mb.EnumObjects("/RouteDomains", szDomainName, dw++))
  3482. pInstance->SetRouteDomainParameters(mb,
  3483. szStarDomain, "",
  3484. szActionType,
  3485. szUserName,
  3486. szEtrnDomain,
  3487. szPassword,
  3488. szTargetName,
  3489. &LocalDomainInfo);
  3490. if (pInstance->AlwaysUseSmartHost() && pInstance->m_szSmartHostName[0]) {
  3491. LocalDomainInfo.dwDomainInfoFlags |= DOMAIN_INFO_REMOTE_SMARTHOST;
  3492. LocalDomainInfo.szSmartHostDomainName = pInstance->m_szSmartHostName;
  3493. LocalDomainInfo.cbSmartHostDomainNameLength = lstrlen(pInstance->m_szSmartHostName);
  3494. }
  3495. //check if we should always use SSL
  3496. if (pInstance->GetDefaultRouteAction() & SMTP_SSL) {
  3497. LocalDomainInfo.dwDomainInfoFlags |= DOMAIN_INFO_USE_SSL;
  3498. }
  3499. hr = pInstance->m_pIAdvQueueConfig->SetDomainInfo(&LocalDomainInfo);
  3500. // jstamerj 1998/07/24 11:18:39:
  3501. // For M2, AQueue requires a local domain entry " " in its
  3502. // configuration to handle recipients without SMTP addresses
  3503. // (such as an remote X400 address). This will be removed when
  3504. // code is added to encapsualte non-SMTP addresses into SMTP.
  3505. // Add this local domain here.
  3506. //
  3507. ZeroMemory(&LocalDomainInfo, sizeof(DomainInfo));
  3508. LocalDomainInfo.cbVersion = sizeof(DomainInfo);
  3509. LocalDomainInfo.cbDomainNameLength = 1;
  3510. LocalDomainInfo.szDomainName = " ";
  3511. LocalDomainInfo.dwDomainInfoFlags = DOMAIN_INFO_LOCAL_MAILBOX;
  3512. hr = pInstance->m_pIAdvQueueConfig->SetDomainInfo(&LocalDomainInfo);
  3513. //Signal AQ that we are finished updating domain config
  3514. pInstance->m_pIAdvQueueConfig->FinishConfigUpdate();
  3515. pInstance->ExclusiveUnLockGenCrit();
  3516. TraceFunctLeaveEx((LPARAM)pInstance);
  3517. return TRUE;
  3518. }
  3519. BOOL SMTP_SERVER_INSTANCE::ReadIpSecList(void)
  3520. {
  3521. IMDCOM* pMBCom;
  3522. METADATA_HANDLE hMB;
  3523. HRESULT hRes;
  3524. METADATA_RECORD mdRecord;
  3525. DWORD dwRequiredLen;
  3526. DWORD dwErr;
  3527. BOOL fSuccess;
  3528. m_GenLock.ExclusiveLock();
  3529. m_rfAccessCheck.Reset( (IMDCOM*)m_Service->QueryMDObject() );
  3530. pMBCom = (IMDCOM*)m_Service->QueryMDObject();
  3531. hRes = pMBCom->ComMDOpenMetaObject( METADATA_MASTER_ROOT_HANDLE,
  3532. (BYTE *) QueryMDPath(),
  3533. METADATA_PERMISSION_READ,
  3534. 5000,
  3535. &hMB );
  3536. if ( SUCCEEDED( hRes ) ) {
  3537. mdRecord.dwMDIdentifier = MD_IP_SEC;
  3538. mdRecord.dwMDAttributes = METADATA_INHERIT | METADATA_REFERENCE;
  3539. mdRecord.dwMDUserType = IIS_MD_UT_FILE;
  3540. mdRecord.dwMDDataType = BINARY_METADATA;
  3541. mdRecord.dwMDDataLen = 0;
  3542. mdRecord.pbMDData = (PBYTE)NULL;
  3543. hRes = pMBCom->ComMDGetMetaData( hMB,
  3544. (LPBYTE)"",
  3545. &mdRecord,
  3546. &dwRequiredLen );
  3547. if ( SUCCEEDED( hRes ) && mdRecord.dwMDDataTag ) {
  3548. m_rfAccessCheck.Set( mdRecord.pbMDData,
  3549. mdRecord.dwMDDataLen,
  3550. mdRecord.dwMDDataTag );
  3551. }
  3552. DBG_REQUIRE( SUCCEEDED(pMBCom->ComMDCloseMetaObject( hMB )) );
  3553. } else {
  3554. fSuccess = FALSE;
  3555. dwErr = HRESULTTOWIN32( hRes );
  3556. }
  3557. m_GenLock.ExclusiveUnlock();
  3558. return TRUE;
  3559. }
  3560. BOOL IsNTFS(IN LPCSTR pszRealPath)
  3561. /*++
  3562. Gets file system specific information for a given path.
  3563. It uses GetVolumeInfomration() to query the file system type
  3564. and file system flags.
  3565. On success the flags and file system type are returned in
  3566. passed in pointers.
  3567. --*/
  3568. {
  3569. #define MAX_FILE_SYSTEM_NAME_SIZE ( MAX_PATH)
  3570. CHAR rgchBuf[MAX_FILE_SYSTEM_NAME_SIZE];
  3571. CHAR rgchRoot[MAX_FILE_SYSTEM_NAME_SIZE];
  3572. int i;
  3573. DWORD dwReturn = ERROR_PATH_NOT_FOUND;
  3574. if ( pszRealPath == NULL) {
  3575. return FALSE;
  3576. }
  3577. if ( pszRealPath[0] == ('\\') &&
  3578. pszRealPath[1] == ('\\')) {
  3579. return FALSE;
  3580. } // else
  3581. ZeroMemory( (void *) rgchRoot, sizeof(rgchRoot) );
  3582. //
  3583. // This is non UNC name.
  3584. // Copy just the root directory to rgchRoot for querying
  3585. //
  3586. for ( i = 0; i < 9 && pszRealPath[i] != '\0'; i++) {
  3587. if ( (rgchRoot[i] = pszRealPath[i]) == ':') {
  3588. break;
  3589. }
  3590. } // for
  3591. if ( rgchRoot[i] != ':') {
  3592. //
  3593. // we could not find the root directory.
  3594. // return with error value
  3595. //
  3596. return ( FALSE);
  3597. }
  3598. rgchRoot[i+1] = '\\'; // terminate the drive spec with a slash
  3599. rgchRoot[i+2] = '\0'; // terminate the drive spec with null char
  3600. // The rgchRoot should end with a "\" (slash)
  3601. // otherwise, the call will fail.
  3602. if ( GetVolumeInformation( rgchRoot, // lpRootPathName
  3603. NULL, // lpVolumeNameBuffer
  3604. 0, // len of volume name buffer
  3605. NULL, // lpdwVolSerialNumber
  3606. NULL, // lpdwMaxComponentLength
  3607. NULL, // lpdwSystemFlags
  3608. rgchBuf, // lpFileSystemNameBuff
  3609. sizeof(rgchBuf)/sizeof(WCHAR)
  3610. )) {
  3611. if ( lstrcmp( rgchBuf, "NTFS") == 0) {
  3612. return TRUE;
  3613. }
  3614. }
  3615. return ( FALSE);
  3616. }
  3617. //+---------------------------------------------------------------
  3618. //
  3619. // Function: SMTPCONFIG::ReadStartupRegParams
  3620. //
  3621. // Synopsis: Reads fixed (i.e. not modifiable on-the-fly) parameters
  3622. // from the registry into the config class member variables.
  3623. //
  3624. // Arguments: None
  3625. //
  3626. // Returns: BOOL - TRUE on SUCCESS, FALSE on FAIL
  3627. //
  3628. // Note: Created by KeithLau on 7/15/96
  3629. //
  3630. //----------------------------------------------------------------
  3631. BOOL SMTP_SERVER_INSTANCE::ReadStartupRegParams(VOID)
  3632. {
  3633. BOOL fRet = TRUE;
  3634. DWORD dwErr = NO_ERROR;
  3635. DWORD dwAttr;
  3636. char szValueName[MAX_PATH + 1];
  3637. MB mb( (IMDCOM*) g_pInetSvc->QueryMDObject() );
  3638. STR TempString;
  3639. const CHAR * apszSubStrings[2];
  3640. CHAR pchAddr1[32] = "";
  3641. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::ReadStartupRegParams");
  3642. GetServerBindings();
  3643. m_GenLock.ExclusiveLock();
  3644. //
  3645. // Read metabase data.
  3646. //
  3647. lstrcpy(szValueName, QueryMDPath());
  3648. _itoa(QueryInstanceId(), pchAddr1, 10);
  3649. if ( !mb.Open( szValueName, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE) ) {
  3650. //UnLockConfig();
  3651. m_GenLock.ExclusiveUnlock();
  3652. return FALSE;
  3653. }
  3654. m_CmdLogFlags = ReadMetabaseDword(mb, MD_COMMAND_LOG_MASK, DEFAULT_CMD_LOG_FLAGS);
  3655. m_fFlushMailFiles = !!ReadMetabaseDword(mb, MD_FLUSH_MAIL_FILE, TRUE);
  3656. m_cMaxRoutingThreads = ReadMetabaseDword(mb, MD_ROUTING_THREADS, 8);
  3657. StateTrace((LPARAM)this, "m_cMaxRoutingThreads = %u", m_cMaxRoutingThreads);
  3658. m_fDisablePickupDotStuff = !!ReadMetabaseDword(mb, MD_SMTP_DISABLE_PICKUP_DOT_STUFF, FALSE);
  3659. StateTrace((LPARAM)this, "m_fDisablePickupDotStuff = %u", m_fDisablePickupDotStuff);
  3660. m_cMaxRemoteQThreads = ReadMetabaseDword(mb, MD_SMTP_MAX_REMOTEQ_THREADS, 1);
  3661. StateTrace((LPARAM)this, "m_cMaxRoutingThreads = %u",m_cMaxRemoteQThreads);
  3662. m_cMaxLocalQThreads = ReadMetabaseDword(mb, MD_SMTP_MAX_LOCALQ_THREADS, 1);
  3663. StateTrace((LPARAM)this, "m_cMaxRoutingThreads = %u", m_cMaxLocalQThreads);
  3664. TempString.Reset();
  3665. if (!mb.GetStr("", MD_MAIL_QUEUE_DIR, IIS_MD_UT_SERVER, &TempString, 0) ||
  3666. TempString.IsEmpty()) {
  3667. // We had a problem reading the registry.
  3668. // This is a very bad thing. We obviously cannot run without
  3669. // a queue directory, so set fRet to FALSE so that we shut
  3670. // back down (and log it so that an admin can fix it).
  3671. m_szMailQueueDir[0] = '\0';
  3672. fRet = FALSE;
  3673. apszSubStrings[0] = pchAddr1;
  3674. apszSubStrings[1] = szMailQueueDir;
  3675. SmtpLogEvent(SMTP_EVENT_CANNOT_READ_SVC_REGKEY, 2, apszSubStrings, 0);
  3676. } else {
  3677. lstrcpyn(m_szMailQueueDir, TempString.QueryStr(), MAX_PATH);
  3678. if (!IsNTFS(m_szMailQueueDir)) {
  3679. m_IsFileSystemNtfs = FALSE;
  3680. DebugTrace((LPARAM)this, "Queue dir (%s) is not NTFS", m_szMailQueueDir);
  3681. }
  3682. // We found a path in the reg, so see if we can use it...
  3683. dwAttr = GetFileAttributes(m_szMailQueueDir);
  3684. if (dwAttr == 0xFFFFFFFF) {
  3685. // The path doesn't exist yet, so we'll try to create it.
  3686. if (!CreateLayerDirectory(m_szMailQueueDir) && (dwErr = GetLastError()) != ERROR_ALREADY_EXISTS) {
  3687. // It doesn't exist and we couldn't create it, so
  3688. // log it and bail with fRet = FALSE so that we shut
  3689. // back down.
  3690. ErrorTrace((LPARAM)this, "Unable to create mail queue directory (%s)", m_szMailQueueDir);
  3691. apszSubStrings[0] = pchAddr1;
  3692. apszSubStrings[1] = m_szMailQueueDir;
  3693. SmtpLogEvent(SMTP_EVENT_INVALID_MAIL_QUEUE_DIR, 2, apszSubStrings, dwErr);
  3694. m_szMailQueueDir[0] = '\0';
  3695. fRet = FALSE;
  3696. }
  3697. } else {
  3698. if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) {
  3699. // The registry points to a file, so we're outta luck.
  3700. // The directory doesn't exist, and we can't create it.
  3701. // Because this is the queue directory, we're not going
  3702. // to be able to start. Log it so it can be fixed, but
  3703. // set fRet to FALSE so that we shut back down.
  3704. ErrorTrace((LPARAM)this, "Mail queue directory (%s) already exists as a file", m_szMailQueueDir);
  3705. apszSubStrings[0] = pchAddr1;
  3706. apszSubStrings[1] = m_szMailQueueDir;
  3707. SmtpLogEvent(SMTP_EVENT_INVALID_MAIL_QUEUE_DIR, 2, apszSubStrings, dwErr);
  3708. m_szMailQueueDir[0] = '\0';
  3709. fRet = FALSE;
  3710. }
  3711. }
  3712. }
  3713. TempString.Reset();
  3714. if (! mb.GetStr("", MD_MAIL_DROP_DIR, IIS_MD_UT_SERVER, &TempString, 0) ||
  3715. TempString.IsEmpty()) {
  3716. // We had a problem reading the metabase.
  3717. // This is a very bad thing. We obviously cannot run without
  3718. // a drop directory if we are in drop mode, so set fRet to
  3719. // FALSE so that we shut back down (and log it so that an
  3720. // admin can fix it).
  3721. m_szMailDropDir[0] = '\0';
  3722. m_cchMailDropDir = 0;
  3723. //don't start if we are disabled, since drop directory is not
  3724. //configurable.
  3725. if (!m_fIsRoutingTable) {
  3726. fRet = FALSE;
  3727. apszSubStrings[0] = pchAddr1;
  3728. apszSubStrings[1] = szMailDropDir;
  3729. SmtpLogEvent(SMTP_EVENT_CANNOT_READ_SVC_REGKEY, 2, apszSubStrings, 0);
  3730. }
  3731. } else {
  3732. lstrcpyn(m_szMailDropDir, TempString.QueryStr(), MAX_PATH);
  3733. apszSubStrings[0] = pchAddr1;
  3734. apszSubStrings[1] = m_szMailDropDir;
  3735. // We found a path in the reg, so see if we can use it...
  3736. dwAttr = GetFileAttributes(m_szMailDropDir);
  3737. if (dwAttr == 0xFFFFFFFF) {
  3738. // The path doesn't exist yet, so we'll try to create it.
  3739. if (!CreateLayerDirectory(m_szMailDropDir) && (dwErr = GetLastError()) != ERROR_ALREADY_EXISTS) {
  3740. // It doesn't exist and we couldn't create it, so
  3741. // log it and bail with fRet = FALSE so that we shut
  3742. // back down.
  3743. ErrorTrace((LPARAM)this, "Unable to create mail drop directory (%s)", m_szMailQueueDir);
  3744. apszSubStrings[0] = pchAddr1;
  3745. apszSubStrings[1] = m_szMailDropDir;
  3746. SmtpLogEvent(SMTP_EVENT_INVALID_MAIL_DROP_DIR, 2, apszSubStrings, dwErr);
  3747. m_szMailDropDir[0] = '\0';
  3748. m_cchMailDropDir = 0;
  3749. //don't start if we are disabled, since drop directory is not
  3750. //configurable.
  3751. if (!m_fIsRoutingTable)
  3752. fRet = FALSE;
  3753. }
  3754. } else {
  3755. if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) {
  3756. // The registry points to a file, so we're outta luck.
  3757. // The directory doesn't exist, and we can't create it.
  3758. // Because this is the queue directory, we're not going
  3759. // to be able to start. Log it so it can be fixed, but
  3760. // set fRet to FALSE so that we shut back down.
  3761. ErrorTrace((LPARAM)this, "Mail drop directory (%s) already exists as a file", m_szMailDropDir);
  3762. apszSubStrings[0] = pchAddr1;
  3763. apszSubStrings[1] = m_szMailDropDir;
  3764. SmtpLogEvent(SMTP_EVENT_INVALID_MAIL_DROP_DIR, 2, apszSubStrings, dwErr);
  3765. m_szMailDropDir[0] = '\0';
  3766. //don't start if we are disabled, since drop directory is not
  3767. //configurable.
  3768. if (!m_fIsRoutingTable)
  3769. fRet = FALSE;
  3770. }
  3771. }
  3772. // Looks like everything is going to be OK, so we add a backslash (if
  3773. // necessary) because it makes things easier later.
  3774. m_cchMailDropDir = lstrlen(m_szMailDropDir);
  3775. if (m_cchMailDropDir > 0 && m_szMailDropDir[m_cchMailDropDir - 1] != '\\') {
  3776. lstrcat(m_szMailDropDir, "\\");
  3777. m_cchMailDropDir++;
  3778. }
  3779. }
  3780. // Looks like everything is going to be OK, so we add a backslash (if
  3781. // necessary) because it makes things easier later.
  3782. m_cchMailQueueDir = lstrlen(m_szMailQueueDir);
  3783. if (m_cchMailQueueDir > 0 && m_szMailQueueDir[m_cchMailQueueDir - 1] != '\\') {
  3784. lstrcat(m_szMailQueueDir, "\\");
  3785. m_cchMailQueueDir++;
  3786. }
  3787. m_fShouldPickupMail = !!ReadMetabaseDword(mb, MD_SHOULD_PICKUP_MAIL, TRUE);
  3788. if (m_fShouldPickupMail) {
  3789. m_cMaxDirBuffers = ReadMetabaseDword(mb, MD_MAX_DIR_BUFFERS, 2000);
  3790. m_cMaxDirChangeIoSize = ReadMetabaseDword(mb, MD_MAX_DIR_CHANGE_IO_SIZE, 1000);
  3791. m_cMaxDirPendingIos = ReadMetabaseDword(mb, MD_MAX_DIR_PENDING_IOS, 1);
  3792. TempString.Reset();
  3793. if (!mb.GetStr("", MD_MAIL_PICKUP_DIR, IIS_MD_UT_SERVER, &TempString, 0) ||
  3794. TempString.IsEmpty()) {
  3795. // We had a problem reading the registry.
  3796. // This is a very bad thing.
  3797. m_szMailPickupDir[0] = '\0';
  3798. m_fShouldPickupMail = 0;
  3799. apszSubStrings[0] = pchAddr1;
  3800. apszSubStrings[1] = szMailPickupDir;
  3801. SmtpLogEvent(SMTP_EVENT_CANNOT_READ_SVC_REGKEY, 2, apszSubStrings, 0);
  3802. } else {
  3803. lstrcpyn(m_szMailPickupDir, TempString.QueryStr(), MAX_PATH);
  3804. // We found a path in the reg, so see if we can use it...
  3805. dwAttr = GetFileAttributes(m_szMailPickupDir);
  3806. if (dwAttr == 0xFFFFFFFF) {
  3807. // The path doesn't exist yet, so we'll try to create it.
  3808. if (!CreateLayerDirectory(m_szMailPickupDir) && (dwErr = GetLastError()) != ERROR_ALREADY_EXISTS) {
  3809. // It doesn't exist and we couldn't create it, so
  3810. // log it and bail with fRet = FALSE so that we shut
  3811. // back down.
  3812. ErrorTrace((LPARAM)this, "Unable to create mail pickup queue directory (%s)", m_szMailPickupDir);
  3813. apszSubStrings[0] = pchAddr1;
  3814. apszSubStrings[1] = m_szMailPickupDir;
  3815. SmtpLogEvent(SMTP_EVENT_INVALID_MAIL_DROP_DIR, 2, apszSubStrings, dwErr);
  3816. m_szMailPickupDir[0] = '\0';
  3817. m_fShouldPickupMail = 0;
  3818. }
  3819. } else {
  3820. if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) {
  3821. // The registry points to a file, so we're outta luck.
  3822. // The directory doesn't exist, and we can't create it.
  3823. ErrorTrace((LPARAM)this, "Mail pickup queue directory (%s) already exists as a file", m_szMailPickupDir);
  3824. apszSubStrings[0] = pchAddr1;
  3825. apszSubStrings[1] = m_szMailPickupDir;
  3826. SmtpLogEvent(SMTP_EVENT_INVALID_MAIL_DROP_DIR, 2, apszSubStrings, dwErr);
  3827. m_szMailPickupDir[0] = '\0';
  3828. m_fShouldPickupMail = 0;
  3829. }
  3830. }
  3831. }
  3832. // Looks like everything is going to be OK, so we add a backslash (if
  3833. // necessary) because it makes things easier later.
  3834. m_cchMailPickupDir = lstrlen(m_szMailPickupDir);
  3835. if (m_cchMailPickupDir > 0 && m_szMailPickupDir[m_cchMailPickupDir - 1] != '\\') {
  3836. lstrcat(m_szMailPickupDir, "\\");
  3837. m_cchMailPickupDir++;
  3838. }
  3839. }
  3840. if (!mb.GetStr("", MD_CONNECT_RESPONSE, IIS_MD_UT_SERVER, &TempString) ||
  3841. TempString.IsEmpty()) {
  3842. // We had a problem reading the metabase
  3843. // This is a very bad thing.
  3844. lstrcpy (m_szConnectResponse, "Microsoft ESMTP MAIL Service, ");
  3845. lstrcat (m_szConnectResponse, g_VersionString);
  3846. lstrcat (m_szConnectResponse, " ready at ");
  3847. // SmtpLogEvent(SMTP_EVENT_CANNOT_READ_SVC_REGKEY, 2, apszSubStrings, 0);
  3848. } else {
  3849. lstrcpyn(m_szConnectResponse, TempString.QueryStr(), MAX_PATH);
  3850. }
  3851. m_cchConnectResponse = lstrlenA(m_szConnectResponse);
  3852. mb.Close();
  3853. m_GenLock.ExclusiveUnlock();
  3854. ReadIpSecList();
  3855. if (!fRet)
  3856. SetLastError(ERROR_PATH_NOT_FOUND);
  3857. TraceFunctLeaveEx((LPARAM)this);
  3858. return fRet;
  3859. }
  3860. void SMTP_SERVER_INSTANCE::GetServerBindings(void)
  3861. {
  3862. DWORD dwErr = NO_ERROR;
  3863. MB mb( (IMDCOM*)g_pInetSvc->QueryMDObject() );
  3864. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::GetServerBindings");
  3865. m_GenLock.ExclusiveLock();
  3866. //
  3867. // open metabase data.
  3868. //
  3869. if ( !mb.Open( QueryMDPath(), METADATA_PERMISSION_READ ) ) {
  3870. m_GenLock.ExclusiveUnlock();
  3871. TraceFunctLeaveEx((LPARAM)this);
  3872. return ;
  3873. }
  3874. m_ServerBindings.Reset();
  3875. if (!mb.GetMultisz("", MD_SERVER_BINDINGS, IIS_MD_UT_SERVER, &m_ServerBindings) ||
  3876. m_ServerBindings.IsEmpty()) {
  3877. dwErr = GetLastError();
  3878. ErrorTrace((LPARAM)this, "Unable to read server bindings, error = %u", dwErr);
  3879. }
  3880. m_GenLock.ExclusiveUnlock();
  3881. TraceFunctLeaveEx((LPARAM)this);
  3882. }
  3883. VOID
  3884. SMTP_SERVER_INSTANCE::MDChangeNotify(
  3885. MD_CHANGE_OBJECT * pco
  3886. )
  3887. /*++
  3888. This method handles the metabase change notification for this instance
  3889. Arguments:
  3890. hMDHandle - Metabase handle generating the change notification
  3891. pcoChangeList - path and id that has changed
  3892. --*/
  3893. {
  3894. FIELD_CONTROL control = 0;
  3895. BOOL fSslModified = FALSE;
  3896. DWORD i;
  3897. DWORD err;
  3898. DWORD id;
  3899. DWORD MdState;
  3900. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::MDChangeNotify");
  3901. //
  3902. // Tell our parent about the change notification first
  3903. //
  3904. LockThisForWrite();
  3905. IIS_SERVER_INSTANCE::MDChangeNotify( pco );
  3906. // Save change object
  3907. m_pChangeObject = pco;
  3908. for ( i = 0; i < pco->dwMDNumDataIDs; i++ ) {
  3909. id = pco->pdwMDDataIDs[i];
  3910. switch ( id ) {
  3911. case MD_REVERSE_NAME_LOOKUP:
  3912. control |= FC_SMTP_INFO_REVERSE_LOOKUP;
  3913. break;
  3914. case MD_NTAUTHENTICATION_PROVIDERS:
  3915. control |= FC_SMTP_INFO_NTAUTHENTICATION_PROVIDERS;
  3916. break;
  3917. case MD_MD_SERVER_SS_AUTH_MAPPING:
  3918. case MD_SMTP_CLEARTEXT_AUTH_PROVIDER:
  3919. control |= FC_SMTP_CLEARTEXT_AUTH_PROVIDER;
  3920. break;
  3921. case MD_AUTHORIZATION:
  3922. control |= FC_SMTP_INFO_AUTHORIZATION;
  3923. break;
  3924. case MD_HOP_COUNT:
  3925. control |= FC_SMTP_INFO_MAX_HOP_COUNT;
  3926. break;
  3927. case MD_MAX_SMTP_ERRORS:
  3928. case MD_MAX_SMTP_AUTHLOGON_ERRORS:
  3929. control |= FC_SMTP_INFO_MAX_ERRORS;
  3930. break;
  3931. case MD_MAX_MSG_SIZE:
  3932. case MD_MAX_MSG_SIZE_B4_CLOSE:
  3933. control |= FC_SMTP_INFO_MAX_SIZE;
  3934. break;
  3935. case MD_REMOTE_TIMEOUT:
  3936. control |= FC_SMTP_INFO_REMOTE_TIMEOUT;
  3937. break;
  3938. case MD_MAX_OUTBOUND_CONNECTION:
  3939. control |= FC_SMTP_INFO_MAX_OUTBOUND_CONN;
  3940. break;
  3941. case MD_MAX_RECIPIENTS:
  3942. control |= FC_SMTP_INFO_MAX_RECIPS;
  3943. break;
  3944. case MD_ETRN_SUBDOMAINS:
  3945. control |= FC_SMTP_INFO_ETRN_SUBDOMAINS;
  3946. break;
  3947. case MD_MAIL_DROP_DIR:
  3948. control |= FC_SMTP_INFO_DEFAULT_DROP_DIR;
  3949. control |= FC_SMTP_INFO_DOMAIN_ROUTING;
  3950. break;
  3951. case MD_LOCAL_RETRY_ATTEMPTS:
  3952. case MD_LOCAL_RETRY_MINUTES:
  3953. case MD_REMOTE_RETRY_ATTEMPTS:
  3954. case MD_REMOTE_RETRY_MINUTES:
  3955. // case MD_SHARE_RETRY_MINUTES:
  3956. case MD_SMTP_REMOTE_RETRY_THRESHOLD:
  3957. case MD_SMTP_REMOTE_PROGRESSIVE_RETRY_MINUTES:
  3958. case MD_SMTP_EXPIRE_REMOTE_NDR_MIN:
  3959. case MD_SMTP_EXPIRE_REMOTE_DELAY_MIN:
  3960. case MD_SMTP_EXPIRE_LOCAL_NDR_MIN:
  3961. case MD_SMTP_EXPIRE_LOCAL_DELAY_MIN:
  3962. control |= FC_SMTP_INFO_RETRY;
  3963. break;
  3964. case MD_SHOULD_PIPELINE_OUT:
  3965. case MD_SHOULD_PIPELINE_IN:
  3966. control |= FC_SMTP_INFO_PIPELINE;
  3967. break;
  3968. case MD_SMTP_DS_TYPE:
  3969. case MD_SMTP_DS_DATA_DIRECTORY:
  3970. case MD_SMTP_DS_DEFAULT_MAIL_ROOT:
  3971. case MD_SMTP_DS_BIND_TYPE:
  3972. case MD_SMTP_DS_SCHEMA_TYPE:
  3973. case MD_SMTP_DS_HOST:
  3974. case MD_SMTP_DS_NAMING_CONTEXT:
  3975. case MD_SMTP_DS_ACCOUNT:
  3976. case MD_SMTP_DS_PASSWORD:
  3977. case MD_SMTP_DS_DOMAIN:
  3978. case MD_SMTP_DS_USE_CAT:
  3979. case MD_SMTP_DS_PORT:
  3980. case MD_SMTP_DS_FLAGS:
  3981. control |= FC_SMTP_INFO_ROUTING;
  3982. break;
  3983. case MD_SEND_BAD_TO:
  3984. case MD_SEND_NDR_TO:
  3985. control |= FC_SMTP_INFO_SEND_TO_ADMIN;
  3986. break;
  3987. case MD_SMARTHOST_TYPE:
  3988. case MD_SMARTHOST_NAME:
  3989. control |= FC_SMTP_INFO_SMART_HOST;
  3990. control |= FC_SMTP_INFO_DOMAIN_ROUTING;
  3991. break;
  3992. case MD_NAME_RESOLUTION_TYPE:
  3993. case MD_BATCH_MSG_LIMIT:
  3994. case MD_SMTP_IP_RELAY_ADDRESSES:
  3995. case MD_SMTP_DISABLE_RELAY:
  3996. case MD_SMTP_MAIL_NO_HELO:
  3997. case MD_SMTP_HELO_NODOMAIN:
  3998. case MD_SMTP_DISABLE_PICKUP_DOT_STUFF:
  3999. case MD_SMTP_EVENTLOG_LEVEL:
  4000. control |= FC_SMTP_INFO_COMMON_PARAMS;
  4001. break;
  4002. case MD_DEFAULT_DOMAIN_VALUE:
  4003. control |= FC_SMTP_INFO_DEFAULT_DOMAIN;
  4004. control |= FC_SMTP_INFO_DOMAIN_ROUTING;
  4005. break;
  4006. case MD_FQDN_VALUE:
  4007. control |= FC_SMTP_INFO_FQDN;
  4008. control |= FC_SMTP_INFO_DOMAIN_ROUTING;
  4009. break;
  4010. case MD_BAD_MAIL_DIR:
  4011. control |= FC_SMTP_INFO_BAD_MAIL_DIR;
  4012. break;
  4013. case MD_DO_MASQUERADE:
  4014. case MD_MASQUERADE_NAME:
  4015. control |= FC_SMTP_INFO_MASQUERADE;
  4016. break;
  4017. case MD_REMOTE_SMTP_PORT:
  4018. control |= FC_SMTP_INFO_REMOTE_PORT;
  4019. break;
  4020. case MD_LOCAL_DOMAINS:
  4021. control |= FC_SMTP_INFO_LOCAL_DOMAINS;
  4022. break;
  4023. case MD_DOMAIN_ROUTING:
  4024. control |= FC_SMTP_INFO_DOMAIN_ROUTING;
  4025. break;
  4026. case MD_POSTMASTER_EMAIL:
  4027. case MD_POSTMASTER_NAME:
  4028. control |= FC_SMTP_INFO_ADMIN_EMAIL_NAME;
  4029. break;
  4030. case MD_SMTP_SSL_REQUIRE_TRUSTED_CA:
  4031. case MD_SMTP_SSL_CERT_HOSTNAME_VALIDATION:
  4032. case MD_SSL_ACCESS_PERM:
  4033. control |= FC_SMTP_INFO_SSL_PERM;
  4034. break;
  4035. case MD_SASL_LOGON_DOMAIN:
  4036. control |= FC_SMTP_INFO_SASL_LOGON_DOMAIN;
  4037. break;
  4038. case MD_MAX_OUT_CONN_PER_DOMAIN:
  4039. control |= FC_SMTP_INFO_MAX_OUT_CONN_PER_DOMAIN;
  4040. break;
  4041. case MD_INBOUND_COMMAND_SUPPORT_OPTIONS:
  4042. case MD_OUTBOUND_COMMAND_SUPPORT_OPTIONS:
  4043. case MD_ADD_NOHEADERS :
  4044. control |= FC_SMTP_INFO_INBOUND_SUPPORT_OPTIONS;
  4045. break;
  4046. case MD_SERVER_BINDINGS:
  4047. GetServerBindings();
  4048. break;
  4049. case MD_IP_SEC:
  4050. control |= FC_SMTP_INFO_DOMAIN_ROUTING;
  4051. ReadIpSecList();
  4052. break;
  4053. case MD_SMTP_RELAY_FOR_AUTH_USERS:
  4054. control |= FC_SMTP_INFO_DOMAIN_ROUTING;
  4055. control |= FC_SMTP_INFO_COMMON_PARAMS;
  4056. break;
  4057. case MD_DOMAIN_VALIDATION_FLAGS:
  4058. control |= FC_SMTP_INFO_COMMON_PARAMS;
  4059. break;
  4060. case MD_ROUTE_ACTION:
  4061. case MD_ROUTE_ACTION_TYPE:
  4062. case MD_ROUTE_USER_NAME:
  4063. case MD_ROUTE_PASSWORD:
  4064. case MD_ROUTE_AUTHTARGET:
  4065. case MD_SMTP_CSIDE_ETRN_DELAY:
  4066. case MD_SMTP_CSIDE_ETRN_DOMAIN:
  4067. case MD_SMTP_AUTHORIZED_TURN_LIST:
  4068. control |= FC_SMTP_INFO_DOMAIN_ROUTING;
  4069. break;
  4070. case MD_SSL_CERT_HASH:
  4071. case MD_SSL_CERT_CONTAINER:
  4072. case MD_SSL_CERT_PROVIDER:
  4073. case MD_SSL_CERT_OPEN_FLAGS:
  4074. case MD_SSL_CERT_STORE_NAME:
  4075. case MD_SSL_CTL_IDENTIFIER:
  4076. case MD_SSL_CTL_CONTAINER:
  4077. case MD_SSL_CTL_PROVIDER:
  4078. case MD_SSL_CTL_PROVIDER_TYPE:
  4079. case MD_SSL_CTL_OPEN_FLAGS:
  4080. case MD_SSL_CTL_STORE_NAME:
  4081. fSslModified = TRUE;
  4082. break;
  4083. default:
  4084. break;
  4085. }
  4086. }
  4087. //We need to react to domains being deleted
  4088. // 9/29/98 - MikeSwa
  4089. if (MD_CHANGE_TYPE_DELETE_OBJECT == pco->dwMDChangeType) {
  4090. control |= FC_SMTP_INFO_DOMAIN_ROUTING;
  4091. }
  4092. //
  4093. // If anything related to SSL has changed, call the function used to flush
  4094. // the SSL/Schannel credential cache and reset the server certificate
  4095. //
  4096. if ( fSslModified && g_pSslKeysNotify ) {
  4097. (g_pSslKeysNotify) ( SIMSSL_NOTIFY_MAPPER_SSLKEYS_CHANGED, this );
  4098. ResetSSLInfo(this);
  4099. }
  4100. MdState = QueryServerState( );
  4101. if ( (MdState == MD_SERVER_STATE_STOPPING) || (MdState == MD_SERVER_STATE_STOPPED)) {
  4102. goto Done;
  4103. }
  4104. if ( control != 0 ) {
  4105. if (!ReadRegParams(control, FALSE)) {
  4106. err = GetLastError();
  4107. DBGPRINTF((
  4108. DBG_CONTEXT,
  4109. "SMTP_SERVER_INSTANCE::MDChangeNotify() cannot read config, error %lx\n",
  4110. err
  4111. ));
  4112. }
  4113. }
  4114. // Handle deleting domains
  4115. if (control & FC_SMTP_INFO_DOMAIN_ROUTING)
  4116. {
  4117. // We are deleting objects
  4118. if (pco->dwMDChangeType == MD_CHANGE_TYPE_DELETE_OBJECT) {
  4119. if (!RemoveRegParams(NULL)) {
  4120. err = GetLastError();
  4121. DBGPRINTF((
  4122. DBG_CONTEXT,
  4123. "SMTP_SERVER_INSTANCE::MDChangeNotify() cannot remove config, error %lx\n",
  4124. err
  4125. ));
  4126. }
  4127. }
  4128. }
  4129. Done:
  4130. m_pChangeObject = NULL;
  4131. UnlockThis();
  4132. TraceFunctLeaveEx((LPARAM)this);
  4133. }
  4134. IIS_SSL_INFO*
  4135. SMTP_SERVER_INSTANCE::QueryAndReferenceSSLInfoObj( VOID )
  4136. /*++
  4137. Description
  4138. Returns SSL info for this instance; calls Reference() before returning
  4139. We actually call GetCertificate( ) here, so the name is really incorrect,
  4140. but changing it will involve asking IIS to change IISTYPES to add the
  4141. new method as a vitual function.
  4142. Arguments:
  4143. None
  4144. Returns:
  4145. Ptr to SSL info object on success, NULL if failure
  4146. --*/
  4147. {
  4148. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::QueryAndReferenceSSLInfoObj");
  4149. IIS_SSL_INFO *pPtr = NULL;
  4150. LockThisForRead();
  4151. //
  4152. // If it's null, we may have to create it - unlock, lock for write and make sure it's
  4153. // still NULL before creating it
  4154. //
  4155. if ( !m_pSSLInfo ) {
  4156. UnlockThis();
  4157. LockThisForWrite();
  4158. //
  4159. // Still null, so create it now
  4160. //
  4161. if ( !m_pSSLInfo ) {
  4162. m_pSSLInfo = new IIS_SSL_INFO( (LPTSTR) QueryMDPath(),
  4163. (IMDCOM *) g_pInetSvc->QueryMDObject() );
  4164. if ( m_pSSLInfo == NULL ) {
  4165. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  4166. UnlockThis();
  4167. return NULL;
  4168. }
  4169. //
  4170. // Acquire an internal reference
  4171. //
  4172. m_pSSLInfo->Reference();
  4173. //
  4174. // Register for changes
  4175. //
  4176. IIS_SERVER_CERT *pCert = m_pSSLInfo->GetCertificate();
  4177. if ( pCert ) {
  4178. // Do logging if we fail to get the certificate
  4179. LogCertStatus();
  4180. }
  4181. //NIMISHK**** Do I need CTL - maybe I can get rid of this call
  4182. IIS_CTL *pCTL = m_pSSLInfo->GetCTL();
  4183. if ( pCTL ) {
  4184. //Do logging if we fail to get the CTL
  4185. LogCTLStatus();
  4186. }
  4187. if ( g_pCAPIStoreChangeNotifier ) {
  4188. if ( pCert && pCert->IsValid() ) {
  4189. if (!g_pCAPIStoreChangeNotifier->RegisterStoreForChange( pCert->QueryStoreName(),
  4190. pCert->QueryStoreHandle(),
  4191. ResetSSLInfo,
  4192. (PVOID) this ) ) {
  4193. DebugTrace((LPARAM)this,
  4194. "Failed to register for change event on store %s",
  4195. pCert->QueryStoreName());
  4196. }
  4197. }
  4198. if ( pCTL && pCTL->IsValid() ) {
  4199. if (!g_pCAPIStoreChangeNotifier->RegisterStoreForChange( pCTL->QueryStoreName(),
  4200. pCTL->QueryOriginalStore(),
  4201. ResetSSLInfo,
  4202. (PVOID) this ) ) {
  4203. DebugTrace((LPARAM)this,
  4204. "Failed to register for change event on store %s",
  4205. pCTL->QueryStoreName());
  4206. }
  4207. }
  4208. if ( ( pCert && pCert->IsValid()) ||
  4209. ( pCTL && pCTL->IsValid() ) ) {
  4210. HCERTSTORE hRootStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A,
  4211. 0,
  4212. NULL,
  4213. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  4214. "ROOT" );
  4215. if ( hRootStore ) {
  4216. //
  4217. // Watch for changes to the ROOT store
  4218. //
  4219. if ( !g_pCAPIStoreChangeNotifier->RegisterStoreForChange( "ROOT",
  4220. hRootStore,
  4221. ResetSSLInfo,
  4222. (PVOID) this ) ) {
  4223. DebugTrace((LPARAM)this,
  4224. "Failed to register for change event on root store");
  4225. }
  4226. CertCloseStore( hRootStore,
  4227. 0 );
  4228. } else {
  4229. DebugTrace((LPARAM)this,
  4230. "Failed to open ROOT store, error 0x%d",
  4231. GetLastError());
  4232. }
  4233. } // if ( pCert || pCTL )
  4234. } // if (g_pCAPIStoreChangeNotifier)
  4235. } // if ( !m_pSSLInfo )
  4236. } //if ( !m_pSSLInfo )
  4237. //
  4238. // At this point, m_pSSLInfo should not be NULL anymore, so add the external reference
  4239. //
  4240. m_pSSLInfo->Reference();
  4241. pPtr = m_pSSLInfo;
  4242. UnlockThis();
  4243. TraceFunctLeaveEx((LPARAM)this);
  4244. return pPtr;
  4245. }
  4246. VOID SMTP_SERVER_INSTANCE::ResetSSLInfo( LPVOID pvParam )
  4247. /*++
  4248. Description:
  4249. Wrapper function for function to call to notify of SSL changes
  4250. Arguments:
  4251. pvParam - pointer to instance for which SSL keys have changed
  4252. Returns:
  4253. Nothing
  4254. --*/
  4255. {
  4256. TraceFunctEnterEx((LPARAM)NULL, "SMTP_SERVER_INSTANCE::ResetSSLInfo");
  4257. //
  4258. // Call function to flush credential cache etc
  4259. //
  4260. if ( g_pSslKeysNotify ) {
  4261. g_pSslKeysNotify( SIMSSL_NOTIFY_MAPPER_SSLKEYS_CHANGED,
  4262. pvParam );
  4263. }
  4264. SMTP_SERVER_INSTANCE *pInst = (SMTP_SERVER_INSTANCE *) pvParam;
  4265. pInst->LockThisForRead();
  4266. if ( pInst->m_pSSLInfo ) {
  4267. pInst->UnlockThis();
  4268. pInst->LockThisForWrite();
  4269. if ( pInst->m_pSSLInfo ) {
  4270. //
  4271. // Stop watching for change notifications
  4272. //
  4273. IIS_SERVER_CERT *pCert = pInst->m_pSSLInfo->QueryCertificate();
  4274. IIS_CTL *pCTL = pInst->m_pSSLInfo->QueryCTL();
  4275. if ( g_pCAPIStoreChangeNotifier ) {
  4276. //
  4277. // Stop watching the store the cert came out of
  4278. //
  4279. if ( pCert && pCert->IsValid() ) {
  4280. g_pCAPIStoreChangeNotifier->UnregisterStore( pCert->QueryStoreName(),
  4281. ResetSSLInfo,
  4282. (PVOID) pvParam );
  4283. }
  4284. //
  4285. // Stop watching the store the CTL came out of
  4286. //
  4287. if ( pCTL && pCTL->IsValid() ) {
  4288. g_pCAPIStoreChangeNotifier->UnregisterStore( pCTL->QueryStoreName(),
  4289. ResetSSLInfo,
  4290. (PVOID) pvParam );
  4291. }
  4292. //
  4293. // Stop watching the ROOT store
  4294. //
  4295. g_pCAPIStoreChangeNotifier->UnregisterStore( "ROOT",
  4296. ResetSSLInfo,
  4297. (PVOID) pvParam );
  4298. }
  4299. //
  4300. // Release internal reference
  4301. //
  4302. IIS_SSL_INFO::Release( pInst->m_pSSLInfo );
  4303. //
  4304. // Next call to QueryAndReferenceSSLObj() will create it again
  4305. //
  4306. pInst->m_pSSLInfo = NULL;
  4307. }
  4308. }
  4309. pInst->UnlockThis();
  4310. TraceFunctLeaveEx((LPARAM)NULL);
  4311. }
  4312. VOID SMTP_SERVER_INSTANCE::LogCertStatus()
  4313. /*++
  4314. Description:
  4315. Writes system log event about status of server certificate if the cert is in some
  4316. way not quite kosher eg expired, revoked, not signature-valid
  4317. Arguments:
  4318. None
  4319. Returns:
  4320. Nothing
  4321. --*/
  4322. {
  4323. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::LogCertStatus");
  4324. _ASSERT( m_pSSLInfo );
  4325. DWORD dwCertValidity = 0;
  4326. //
  4327. // If we didn't construct the cert fully, log an error
  4328. //
  4329. if ( !m_pSSLInfo->QueryCertificate()->IsValid() ) {
  4330. CONST CHAR *apszMsgs[2];
  4331. CHAR achInstance[20];
  4332. CHAR achErrorNumber[20];
  4333. wsprintf( achInstance,
  4334. "%lu",
  4335. QueryInstanceId() );
  4336. wsprintf( achErrorNumber,
  4337. "0x%x",
  4338. GetLastError() );
  4339. apszMsgs[0] = achInstance;
  4340. apszMsgs[1] = achErrorNumber;
  4341. DWORD dwStatus = m_pSSLInfo->QueryCertificate()->Status();
  4342. DWORD dwStringID = 0;
  4343. DebugTrace((LPARAM)this,
  4344. "Couldn't retrieve server cert; status : %d",
  4345. dwStatus);
  4346. switch ( dwStatus ) {
  4347. case CERT_ERR_MB:
  4348. dwStringID = SSL_MSG_CERT_MB_ERROR;
  4349. break;
  4350. case CERT_ERR_CAPI:
  4351. dwStringID = SSL_MSG_CERT_CAPI_ERROR;
  4352. break;
  4353. case CERT_ERR_CERT_NOT_FOUND:
  4354. dwStringID = SSL_MSG_CERT_NOT_FOUND;
  4355. break;
  4356. default:
  4357. dwStringID = SSL_MSG_CERT_INTERNAL_ERROR;
  4358. break;
  4359. }
  4360. SmtpLogEvent(dwStringID,
  4361. 2,
  4362. apszMsgs,
  4363. 0 );
  4364. TraceFunctLeaveEx((LPARAM)this);
  4365. return;
  4366. }
  4367. //
  4368. // If cert is invalid in some other way , write the appropriate log message
  4369. //
  4370. if ( m_pSSLInfo->QueryCertValidity( &dwCertValidity ) ) {
  4371. const CHAR *apszMsgs[1];
  4372. CHAR achInstance[20];
  4373. wsprintfA( achInstance,
  4374. "%lu",
  4375. QueryInstanceId() );
  4376. apszMsgs[0] = achInstance;
  4377. DWORD dwMsgID = 0;
  4378. if ( ( dwCertValidity & CERT_TRUST_IS_NOT_TIME_VALID ) ||
  4379. ( dwCertValidity & CERT_TRUST_IS_NOT_TIME_NESTED ) ||
  4380. ( dwCertValidity & CERT_TRUST_CTL_IS_NOT_TIME_VALID ) ) {
  4381. DebugTrace((LPARAM)this,
  4382. "Server cert/CTL is not time-valid or time-nested");
  4383. dwMsgID = SSL_MSG_TIME_INVALID_SERVER_CERT;
  4384. }
  4385. if ( dwCertValidity & CERT_TRUST_IS_REVOKED ) {
  4386. DebugTrace((LPARAM)this,
  4387. "Server Cert is revoked");
  4388. dwMsgID = SSL_MSG_REVOKED_SERVER_CERT;
  4389. }
  4390. if ( ( dwCertValidity & CERT_TRUST_IS_UNTRUSTED_ROOT ) ||
  4391. ( dwCertValidity & CERT_TRUST_IS_PARTIAL_CHAIN ) ) {
  4392. DebugTrace((LPARAM)this,
  4393. "Server Cert doesn't chain up to a trusted root");
  4394. dwMsgID = SSL_MSG_UNTRUSTED_SERVER_CERT;
  4395. }
  4396. if ( ( dwCertValidity & CERT_TRUST_IS_NOT_SIGNATURE_VALID ) ||
  4397. ( dwCertValidity & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID ) ) {
  4398. DebugTrace((LPARAM)this,
  4399. "Server Cert/CTL is not signature valid");
  4400. dwMsgID = SSL_MSG_SIGNATURE_INVALID_SERVER_CERT;
  4401. }
  4402. if ( dwMsgID ) {
  4403. SmtpLogEvent( dwMsgID,
  4404. 1,
  4405. apszMsgs,
  4406. 0 );
  4407. }
  4408. }
  4409. TraceFunctLeaveEx((LPARAM)this);
  4410. }
  4411. VOID SMTP_SERVER_INSTANCE::LogCTLStatus()
  4412. /*++
  4413. Description:
  4414. Writes system log event about status of server CTL if CTL isn't valid
  4415. Arguments:
  4416. None
  4417. Returns:
  4418. Nothing
  4419. --*/
  4420. {
  4421. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::LogCTLStatus");
  4422. _ASSERT( m_pSSLInfo );
  4423. //
  4424. // If we didn't construct the CTL fully, log an error
  4425. //
  4426. if ( !m_pSSLInfo->QueryCTL()->IsValid() ) {
  4427. CONST CHAR *apszMsgs[2];
  4428. CHAR achInstance[20];
  4429. CHAR achErrorNumber[20];
  4430. wsprintf( achInstance,
  4431. "%lu",
  4432. QueryInstanceId() );
  4433. wsprintf( achErrorNumber,
  4434. "0x%x",
  4435. GetLastError() );
  4436. apszMsgs[0] = achInstance;
  4437. apszMsgs[1] = achErrorNumber;
  4438. DWORD dwStatus = m_pSSLInfo->QueryCTL()->QueryStatus();
  4439. DWORD dwStringID = 0;
  4440. DebugTrace((LPARAM)this,
  4441. "Couldn't retrieve server CTL; status : %d\n",
  4442. dwStatus);
  4443. switch ( dwStatus ) {
  4444. case CERT_ERR_MB:
  4445. dwStringID = SSL_MSG_CTL_MB_ERROR;
  4446. break;
  4447. case CERT_ERR_CAPI:
  4448. dwStringID = SSL_MSG_CTL_CAPI_ERROR;
  4449. break;
  4450. case CERT_ERR_CERT_NOT_FOUND:
  4451. dwStringID = SSL_MSG_CTL_NOT_FOUND;
  4452. break;
  4453. default:
  4454. dwStringID = SSL_MSG_CTL_INTERNAL_ERROR;
  4455. break;
  4456. }
  4457. SmtpLogEvent( dwStringID,
  4458. 2,
  4459. apszMsgs,
  4460. 0 );
  4461. TraceFunctLeaveEx((LPARAM)this);
  4462. return;
  4463. }
  4464. TraceFunctLeaveEx((LPARAM)this);
  4465. }
  4466. BOOL
  4467. SmtpMappingSupportFunction(
  4468. PVOID pvInstance,
  4469. PVOID pData,
  4470. DWORD dwPropId)
  4471. {
  4472. if (dwPropId == SIMSSL_NOTIFY_MAPPER_SSLKEYS_CHANGED) {
  4473. return (SetSslKeysNotify( (PFN_SF_NOTIFY) pData));
  4474. } else if (dwPropId == SIMSSL_NOTIFY_MAPPER_CERT11_CHANGED ||
  4475. dwPropId == SIMSSL_NOTIFY_MAPPER_CERTW_CHANGED) {
  4476. return ( TRUE );
  4477. } else {
  4478. return ( FALSE );
  4479. }
  4480. }
  4481. BOOL
  4482. SetSslKeysNotify(
  4483. PFN_SF_NOTIFY pFn
  4484. )
  4485. /*++
  4486. Description
  4487. Set the function called to notify SSL keys have changed
  4488. Can be called only once
  4489. Arguments:
  4490. pFn - function to call to notify SSL keys change
  4491. Returns:
  4492. TRUE if function reference stored, FALSE otherwise
  4493. --*/
  4494. {
  4495. if ( g_pSslKeysNotify == NULL || pFn == NULL ) {
  4496. g_pSslKeysNotify = pFn;
  4497. return TRUE;
  4498. }
  4499. return FALSE;
  4500. }
  4501. CAddr * SMTP_SERVER_INSTANCE::AppendLocalDomain (CAddr * OldAddress)
  4502. {
  4503. char ReWriteAddr [MAX_INTERNET_NAME + 1];
  4504. CAddr * NewAddress = NULL;
  4505. DWORD TotalSize = 0;
  4506. //If there is no domain on this address,
  4507. //then append the current domain to this
  4508. //address
  4509. m_GenLock.ShareLock();
  4510. TotalSize = lstrlen(OldAddress->GetAddress()) + lstrlen(GetDefaultDomain()) + 1; //+1 for the @
  4511. if ( TotalSize >= MAX_INTERNET_NAME) {
  4512. m_GenLock.ShareUnlock();
  4513. SetLastError(ERROR_INVALID_DATA);
  4514. return NULL;
  4515. }
  4516. lstrcpy(ReWriteAddr, OldAddress->GetAddress());
  4517. lstrcat(ReWriteAddr, "@");
  4518. lstrcat(ReWriteAddr, GetDefaultDomain());
  4519. m_GenLock.ShareUnlock();
  4520. //create a new CAddr
  4521. NewAddress = CAddr::CreateKnownAddress (ReWriteAddr);
  4522. return NewAddress;
  4523. }
  4524. BOOL SMTP_SERVER_INSTANCE::AppendLocalDomain(char * Address)
  4525. {
  4526. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::AppendLocalDomain");
  4527. m_GenLock.ShareLock();
  4528. if ((lstrlen(Address) + lstrlen(GetDefaultDomain()) + 1) > MAX_INTERNET_NAME) {
  4529. //Our concatanated name will be larger than allowed name
  4530. ErrorTrace((LPARAM)this, "Generated address longer than allowed max");
  4531. m_GenLock.ShareUnlock();
  4532. return FALSE;
  4533. }
  4534. lstrcat(Address, "@");
  4535. lstrcat(Address, GetDefaultDomain());
  4536. m_GenLock.ShareUnlock();
  4537. TraceFunctLeaveEx((LPARAM)this);
  4538. return TRUE;
  4539. }
  4540. CAddr * SMTP_SERVER_INSTANCE::MasqueradeDomain (CAddr * OldAddress)
  4541. {
  4542. char ReWriteAddr [MAX_INTERNET_NAME + 1];
  4543. CAddr * NewAddress = NULL;
  4544. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::MasqueradeDomain");
  4545. m_GenLock.ShareLock();
  4546. if (m_fMasquerade) {
  4547. //if there is a domain in the name, get rid of it
  4548. //we are going to replace it with the masquerade
  4549. if (OldAddress->GetDomainOffset()) {
  4550. *(OldAddress->GetDomainOffset()) = '\0';
  4551. }
  4552. lstrcpy(ReWriteAddr, OldAddress->GetAddress());
  4553. lstrcat(ReWriteAddr, "@");
  4554. lstrcat(ReWriteAddr, m_szMasqueradeName);
  4555. //create a new CAddr
  4556. NewAddress = CAddr::CreateKnownAddress (ReWriteAddr);
  4557. }
  4558. m_GenLock.ShareUnlock();
  4559. TraceFunctLeaveEx((LPARAM)this);
  4560. return NewAddress;
  4561. }
  4562. BOOL SMTP_SERVER_INSTANCE::MasqueradeDomain(char * Address, char * DomainPtr)
  4563. {
  4564. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::MasqueradeDomain");
  4565. m_GenLock.ShareLock();
  4566. if (m_fMasquerade) {
  4567. //if there is a domain in the name, get rid of it
  4568. //we are going to replace it with the masquerade
  4569. if (DomainPtr) {
  4570. if ((DomainPtr - Address + lstrlen(m_szMasqueradeName)) > MAX_INTERNET_NAME) {
  4571. //Our concatanated name will be larger than allowed name
  4572. ErrorTrace((LPARAM)this, "Generated address longer than allowed max");
  4573. m_GenLock.ShareUnlock();
  4574. return FALSE;
  4575. }
  4576. lstrcpy(DomainPtr, m_szMasqueradeName);
  4577. } else {
  4578. if ((lstrlen(Address) + lstrlen(m_szMasqueradeName) + 1) > MAX_INTERNET_NAME) {
  4579. //Our concatanated name will be larger than allowed name
  4580. ErrorTrace((LPARAM)this, "Generated address longer than allowed max");
  4581. m_GenLock.ShareUnlock();
  4582. return FALSE;
  4583. }
  4584. lstrcat(Address, "@");
  4585. lstrcat(Address, m_szMasqueradeName);
  4586. }
  4587. }
  4588. m_GenLock.ShareUnlock();
  4589. TraceFunctLeaveEx((LPARAM)this);
  4590. return TRUE;
  4591. }
  4592. extern BOOL IsIpInGlobalList(DWORD IpAddress);
  4593. BOOL SMTP_SERVER_INSTANCE::CompareIpAddress(DWORD IpAddress)
  4594. {
  4595. BOOL fRet = TRUE;
  4596. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::CompareIpAddress");
  4597. if (IpAddress != g_LoopBackAddr) {
  4598. fRet = IsIpInGlobalList(IpAddress);
  4599. } else {
  4600. FatalTrace((LPARAM) this, "IpAddress %d is loopback - Failing connection", IpAddress);
  4601. }
  4602. TraceFunctLeaveEx((LPARAM)this);
  4603. return fRet;
  4604. }
  4605. //Note : When connected port is passed in 0, it only does IP address comparison
  4606. //
  4607. BOOL SMTP_SERVER_INSTANCE::IsAddressMine(DWORD IpAddress, DWORD ConnectedPort)
  4608. {
  4609. char * Ptr = NULL;
  4610. const char * StartPtr = NULL;
  4611. const CHAR * ipAddressString = NULL;
  4612. const CHAR * ipPortString = NULL;
  4613. const CHAR * hostNameString = NULL;
  4614. const CHAR * end = NULL;
  4615. DWORD InetAddr = 0;
  4616. DWORD CharIpSize = 0;
  4617. CHAR temp[sizeof("123.123.123.123")];
  4618. INT length;
  4619. LONG tempPort;
  4620. BOOL BindingMatchFound = FALSE;
  4621. BOOL IpSame = FALSE;
  4622. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::IsAddressMine");
  4623. //grab the sharing lock
  4624. m_GenLock.ShareLock();
  4625. if (m_ServerBindings.IsEmpty()) {
  4626. DebugTrace((LPARAM) this, "Server bindings is emtpy - checking all addresses");
  4627. m_GenLock.ShareUnlock();
  4628. IpSame = CompareIpAddress(IpAddress);
  4629. TraceFunctLeaveEx((LPARAM)this);
  4630. return IpSame;
  4631. } else {
  4632. for (StartPtr = m_ServerBindings.First(); StartPtr != NULL; StartPtr = m_ServerBindings.Next( StartPtr )) {
  4633. ipAddressString = StartPtr;
  4634. ipPortString = strchr(StartPtr, ':');
  4635. if (ipPortString == NULL) {
  4636. goto out;
  4637. }
  4638. ipPortString++;
  4639. hostNameString = strchr( ipPortString, ':' );
  4640. if ( hostNameString == NULL ) {
  4641. goto out;
  4642. }
  4643. hostNameString++;
  4644. //
  4645. // Validate and parse the IP address portion.
  4646. //
  4647. if ( *ipAddressString == ':' ) {
  4648. InetAddr = INADDR_ANY;
  4649. } else {
  4650. length = DIFF(ipPortString - ipAddressString) - 1;
  4651. if ( length > sizeof(temp) ) {
  4652. goto out;
  4653. }
  4654. CopyMemory( temp, ipAddressString, length);
  4655. temp[length] = '\0';
  4656. InetAddr = (DWORD)inet_addr( temp );
  4657. if ( InetAddr == INADDR_NONE ) {
  4658. goto out;
  4659. }
  4660. }//end else of if( *ipAddressString == ':' )
  4661. //
  4662. // Validate and parse the port.
  4663. //
  4664. if ( *ipPortString == ':' ) {
  4665. goto out;
  4666. }
  4667. length = (INT)(hostNameString - ipPortString);
  4668. if ( length > sizeof(temp) ) {
  4669. goto out;
  4670. }
  4671. CopyMemory(temp,ipPortString, length);
  4672. temp[length] = '\0';
  4673. tempPort = strtol( temp, (CHAR **)&end, 0 );
  4674. if ( tempPort <= 0 || tempPort > 0xFFFF ) {
  4675. goto out;
  4676. }
  4677. if ( *end != ':' ) {
  4678. goto out;
  4679. }
  4680. if (InetAddr == INADDR_ANY) {
  4681. IpSame = CompareIpAddress(IpAddress);
  4682. if (IpSame && ((DWORD) tempPort == ConnectedPort) && (ConnectedPort > 0)) {
  4683. BindingMatchFound = TRUE;
  4684. goto out;
  4685. } else if (IpSame && (ConnectedPort == 0)) {
  4686. BindingMatchFound = TRUE;
  4687. goto out;
  4688. }
  4689. } else if ( (IpAddress == InetAddr) && ((DWORD) tempPort == ConnectedPort) && (ConnectedPort > 0)) {
  4690. FatalTrace((LPARAM) this, "IpAddress %d is one of mine - Failing connection", IpAddress);
  4691. BindingMatchFound = TRUE;
  4692. goto out;
  4693. } else if ( (IpAddress == InetAddr) && (ConnectedPort == 0)) {
  4694. BindingMatchFound = TRUE;
  4695. goto out;
  4696. }
  4697. }//end for
  4698. }//end else
  4699. out:
  4700. m_GenLock.ShareUnlock();
  4701. if (!BindingMatchFound)
  4702. DebugTrace((LPARAM) this, "IpAddress %d is not one of mine", IpAddress);
  4703. TraceFunctLeaveEx((LPARAM)this);
  4704. return BindingMatchFound;
  4705. }
  4706. BOOL SMTP_SERVER_INSTANCE::MoveToBadMail ( IMailMsgProperties *pIMsg, BOOL fUseIMsg, char * MailFile, char * FilePath)
  4707. {
  4708. TCHAR BadMailDir[MAX_PATH + 1];
  4709. TCHAR MailPath [MAX_PATH + 1];
  4710. TCHAR StreamPath[MAX_PATH + 1];
  4711. char * pszSearch = NULL;
  4712. BOOL f = TRUE;
  4713. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::MoveToBadMail");
  4714. //concatenate the name of the stream to the file
  4715. lstrcpy(MailPath, FilePath);
  4716. lstrcat(MailPath, MailFile);
  4717. m_GenLock.ShareLock();
  4718. f = SUCCEEDED(m_IAQ->HandleFailedMessage(pIMsg, fUseIMsg, MailPath, MESSAGE_FAILURE_BAD_PICKUP_DIR_FILE, E_FAIL));
  4719. m_GenLock.ShareUnlock();
  4720. TraceFunctLeaveEx((LPARAM)this);
  4721. return f;
  4722. }
  4723. #define NTFS_STORE_DIRECTORY_REG_PATH _T("Software\\Microsoft\\Exchange\\StoreDriver\\Ntfs\\%u")
  4724. #define NTFS_STORE_DIRECTORY_REG_NAME _T("StoreDir")
  4725. #define NTFS_STORE_BACKSLASH _T("\\")
  4726. #define NTFS_QUEUE_DIRECTORY_SUFFIX _T("\\Queue")
  4727. #define NTFS_DROP_DIRECTORY_SUFFIX _T("\\Drop")
  4728. /*++
  4729. Description:
  4730. Initializes server configuration data from registry for SMTP Service.
  4731. Some values are also initialized with constants.
  4732. If invalid registry key or load data from registry fails,
  4733. then use default values.
  4734. Arguments: None
  4735. Returns:
  4736. TRUE if there are no errors.
  4737. Limitations:
  4738. No validity check is performed on the data present in registry.
  4739. --*/
  4740. BOOL SMTP_SERVER_INSTANCE::InitFromRegistry(void)
  4741. {
  4742. LONG err = 0;
  4743. DWORD dwErr = 0;
  4744. DWORD SizeOfBuffer = 0;
  4745. HKEY hkeyTcpipParam = NULL;
  4746. BOOL fRet = FALSE;
  4747. //char szHostName[MAX_PATH + 1];
  4748. // const CHAR * apszSubStrings[2];
  4749. CHAR pchAddr1[32] = "";
  4750. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::InitFromRegistry");
  4751. _itoa(QueryInstanceId(), pchAddr1, 10);
  4752. //
  4753. // This is added by KeithLau on 7/15/96
  4754. // This method loads the registry values that cannot be accessed
  4755. // through the RPC's
  4756. //
  4757. if (!ReadStartupRegParams()) {
  4758. ErrorTrace((LPARAM) this, "Read startup params failed.");
  4759. goto Exit;
  4760. }
  4761. if (!StartAdvancedQueueing()) {
  4762. DebugTrace((LPARAM)this, "Unable to load Advanced Queueing module\n");
  4763. goto Exit;
  4764. }
  4765. fInitializedAQ = TRUE;
  4766. //
  4767. // Metabase Structures... can change at runtime
  4768. // Turn off FC_SMTP_INFO_DEFAULT_DROP_DIR since
  4769. // we already read it in ReadStartupRegParams()
  4770. if (!ReadRegParams(FC_SMTP_INFO_ALL & ~FC_SMTP_INFO_DEFAULT_DROP_DIR, TRUE, FALSE))
  4771. {
  4772. ErrorTrace((LPARAM) this, "Read params failed.");
  4773. goto Exit;
  4774. }
  4775. if (!InitQueues()) {
  4776. err= GetLastError();
  4777. ErrorTrace((LPARAM) this, "can't init queue err = %d", err);
  4778. if (err == NO_ERROR)
  4779. err = ERROR_INVALID_PARAMETER;
  4780. SetLastError(err);
  4781. goto Exit;
  4782. }
  4783. fRet = TRUE;
  4784. Exit:
  4785. TraceFunctLeaveEx((LPARAM)this);
  4786. return fRet;
  4787. }
  4788. /*++
  4789. Adds the new client connection to the list
  4790. of client connections and increments the count of
  4791. clients currently connected to server.
  4792. If the count of max connections is exceeded, then the
  4793. new connection is rejected.
  4794. Arguments:
  4795. pcc pointer to client connection to be added
  4796. Returns:
  4797. TRUE on success and
  4798. FALSE if there is max Connections exceeded.
  4799. --*/
  4800. CLIENT_CONNECTION * SMTP_SERVER_INSTANCE::CreateNewConnection( IN OUT PCLIENT_CONN_PARAMS ClientParam)
  4801. {
  4802. SMTP_CONNECTION * NewConnection = NULL;
  4803. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::InsertNewConnection");
  4804. // We will not accept new connections until the intial queue is built
  4805. if (!m_fShouldStartAcceptingConnections || IsShuttingDown()) {
  4806. return (NULL);
  4807. }
  4808. NewConnection = SMTP_CONNECTION::CreateSmtpConnection (ClientParam, this);
  4809. if (NewConnection != NULL) {
  4810. BUMP_COUNTER(this, NumConnInOpen);
  4811. LockConfig();
  4812. // Increment the count of connected users
  4813. m_cCurrentConnections++;
  4814. // Update the current maximum connections
  4815. if ( m_cCurrentConnections > m_cMaxCurrentConnections) {
  4816. m_cMaxCurrentConnections = m_cCurrentConnections;
  4817. }
  4818. //set the client unique ID
  4819. NewConnection->SetClientId(m_dwNextInboundClientId);
  4820. m_dwNextInboundClientId++;
  4821. //
  4822. // Insert into the list of connected users.
  4823. //
  4824. InsertTailList( &m_ConnectionsList, &NewConnection->QueryListEntry());
  4825. DebugTrace((LPARAM) this, "SMTP_SERVER_INSTANCE:InsertNewConnection succeeded");
  4826. UnLockConfig();
  4827. }
  4828. TraceFunctLeaveEx((LPARAM)this);
  4829. return ( NewConnection);
  4830. }
  4831. void SMTP_SERVER_INSTANCE::StopHint()
  4832. {
  4833. if ( g_pInetSvc && g_pInetSvc->QueryCurrentServiceState() == SERVICE_STOP_PENDING) {
  4834. // 10/28/98 - MikeSwa
  4835. //Use stop hint 30 seconds to avoid problems with commiting many
  4836. //messages on shutdown. (the previous limit of 10 seconds seemed
  4837. //to cause problems with the service control manager).
  4838. g_pInetSvc->UpdateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, m_dwStopHint,
  4839. 30000 ) ;
  4840. m_dwStopHint++ ;
  4841. }
  4842. }
  4843. /*++
  4844. Disconnects all user connections.
  4845. --*/
  4846. VOID SMTP_SERVER_INSTANCE::DisconnectAllConnections( VOID)
  4847. {
  4848. int iteration = 0;
  4849. int i = 0;
  4850. int Count = 0;
  4851. LONG cLastThreadCount = 0;
  4852. DWORD dwLastAllocCount = 0;
  4853. DWORD dwAllocCount;
  4854. int AfterSleepCount = 0;
  4855. DWORD dwStopHint = 2;
  4856. DWORD dwTickCount;
  4857. DWORD dwError = 0;
  4858. PLIST_ENTRY pEntry = NULL;
  4859. SMTP_CONNECTION * pConn = NULL;
  4860. TraceFunctEnter("SMTP_SERVER_INSTANCE::DisconnectAllConnections( VOID)");
  4861. if (m_fShutdownCalled) {
  4862. DebugTrace((LPARAM)this, "m_fShutdownCalled already -- leaving");
  4863. TraceFunctLeaveEx((LPARAM) this);
  4864. }
  4865. //set the global termination flag
  4866. m_IsShuttingDown = TRUE;
  4867. LockConfig();
  4868. TriggerStoreServerEvent(SMTP_STOREDRV_PREPSHUTDOWN_EVENT);
  4869. m_fStoreDrvPrepShutDownEventCalled = TRUE;
  4870. //close down all the active sockets.
  4871. for ( pEntry = m_ConnectionsList.Flink; pEntry != &m_ConnectionsList; pEntry = pEntry->Flink) {
  4872. //get the next connection object
  4873. pConn = (SMTP_CONNECTION *) CONTAINING_RECORD( pEntry, CLIENT_CONNECTION, m_listEntry);
  4874. _ASSERT( pConn != NULL);
  4875. //call the disconnect routine. DisconnectClient() just closes the socket.
  4876. //This will cause all pending I/Os to fail, and have the connections
  4877. //bubble up to the completion routine where they will be removed from
  4878. //the connection list and then distroyed
  4879. pConn->DisconnectClient( ERROR_SERVER_DISABLED);
  4880. }
  4881. UnLockConfig();
  4882. DebugTrace((LPARAM)this, "Cancelling all outstanding SQL queries");
  4883. //
  4884. // Wait for the users to die.
  4885. // The connection objects should be automatically freed because the
  4886. // socket has been closed. Subsequent requests will fail
  4887. // and cause a blowaway of the connection objects.
  4888. // looping is used to get out as early as possible when m_cCurrentConn == 0
  4889. //
  4890. //
  4891. // need to check Pool.GetAllocCount instead of InUseList.Empty
  4892. // because alloc goes to zero during the delete operator
  4893. // instead of during the destructor
  4894. //
  4895. // We sleep at most 120 seconds for a fixed user count.
  4896. //
  4897. dwTickCount = GetTickCount();
  4898. cLastThreadCount = GetProcessClientThreads();
  4899. for (i = 0; i < 180; i++) {
  4900. DebugTrace((LPARAM)this, "Waiting for connections to die, i = %u", i);
  4901. // dwAllocCount = SMTP_CONNECTION::Pool.GetAllocCount();
  4902. dwAllocCount = (DWORD) GetConnInAllocCount();
  4903. if (dwAllocCount == 0 && GetProcessClientThreads() == 0) {
  4904. DebugTrace((LPARAM)this, "All SMTP_CONNECTIONs connections are gone!");
  4905. break;
  4906. }
  4907. Sleep(1000);
  4908. // Update the stop hint checkpoint when we get within 1 second (1000 ms), of the timeout...
  4909. if ((SERVICE_STOP_WAIT_HINT - 1000) < (GetTickCount() - dwTickCount) && g_pInetSvc &&
  4910. g_pInetSvc->QueryCurrentServiceState() == SERVICE_STOP_PENDING) {
  4911. DebugTrace((LPARAM)this, "Updating stop hint, checkpoint = %u", dwStopHint);
  4912. g_pInetSvc->UpdateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, dwStopHint,
  4913. SERVICE_STOP_WAIT_HINT ) ;
  4914. dwStopHint++ ;
  4915. dwTickCount = GetTickCount();
  4916. }
  4917. DebugTrace((LPARAM)this, "Alloc counts: current = %u, last = %u; Thread counts: current = %d, last = %d",
  4918. dwAllocCount, dwLastAllocCount, GetProcessClientThreads(), cLastThreadCount);
  4919. if (dwAllocCount < dwLastAllocCount || GetProcessClientThreads() < cLastThreadCount) {
  4920. DebugTrace((LPARAM)this, "SMTP_CONNECTION Connections are going away, reseting i");
  4921. i = 0;
  4922. }
  4923. dwLastAllocCount = dwAllocCount;
  4924. cLastThreadCount = GetProcessClientThreads();
  4925. }
  4926. if (i == 180) {
  4927. ErrorTrace((LPARAM) this, "%d users won't die", m_cCurrentConnections);
  4928. //
  4929. // once we're thru do it again to find any stray clients
  4930. //
  4931. LockConfig();
  4932. for (pEntry = m_ConnectionsList.Flink;
  4933. pEntry != &m_ConnectionsList;
  4934. pEntry = pEntry->Flink ) {
  4935. //
  4936. // get the next connection object
  4937. //
  4938. pConn = (SMTP_CONNECTION *)CONTAINING_RECORD(pEntry, CLIENT_CONNECTION, m_listEntry);
  4939. _ASSERT(pConn != NULL);
  4940. ErrorTrace( (LPARAM)pConn, "Stray client" );
  4941. }
  4942. UnLockConfig();
  4943. }
  4944. DebugTrace( (LPARAM)this, "SMTP_CONNECTION Count at end is: %d", SMTP_CONNECTION::Pool.GetAllocCount() );
  4945. TraceFunctLeaveEx((LPARAM) this);
  4946. }
  4947. /*++
  4948. Removes the current connection from the list of conenctions
  4949. and decrements count of connected users
  4950. Arguments:
  4951. pcc pointer to client connection to be removed
  4952. --*/
  4953. VOID SMTP_SERVER_INSTANCE::RemoveConnection( IN OUT CLIENT_CONNECTION * pConn)
  4954. {
  4955. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::RemoveConnection");
  4956. _ASSERT( pConn != NULL);
  4957. LockConfig();
  4958. // Remove from list of connections
  4959. RemoveEntryList( &pConn->QueryListEntry());
  4960. // Decrement count of current users
  4961. m_cCurrentConnections--;
  4962. BUMP_COUNTER(this, NumConnInClose);
  4963. UnLockConfig();
  4964. TraceFunctLeaveEx((LPARAM)this);
  4965. } // SMTP_SERVER_INSTANCE::RemoveConnection()
  4966. /*++
  4967. Adds the new client connection to the list
  4968. of outbound client connections and increments the count of
  4969. outbound clients currently connected to server.
  4970. Arguments:
  4971. pcc pointer to client connection to be added
  4972. Returns:
  4973. TRUE on success and
  4974. FALSE if there is max Connections exceeded.
  4975. --*/
  4976. BOOL SMTP_SERVER_INSTANCE::InsertNewOutboundConnection( IN OUT CLIENT_CONNECTION * pcc, BOOL ByPassLimitCheck)
  4977. {
  4978. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::InsertNewOutboundConnection");
  4979. _ASSERT( pcc != NULL);
  4980. m_OutLock.ExclusiveLock();
  4981. // Increment the count of connected users
  4982. m_cCurrentOutConnections++;
  4983. //set the client unique ID
  4984. pcc->SetClientId(m_dwNextOutboundClientId);
  4985. m_dwNextInboundClientId++;
  4986. // Insert into the list of connected outbound users.
  4987. InsertTailList( &m_OutConnectionsList, &pcc->QueryListEntry());
  4988. m_OutLock.ExclusiveUnlock();
  4989. BUMP_COUNTER(this, NumConnOutOpen);
  4990. TraceFunctLeaveEx((LPARAM)this);
  4991. return TRUE;
  4992. }
  4993. BOOL SMTP_SERVER_INSTANCE::InsertAsyncDnsObject( IN OUT CAsyncSmtpDns *pcc)
  4994. {
  4995. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::InsertAsyncDnsObj");
  4996. _ASSERT( pcc != NULL);
  4997. EnterCriticalSection( &m_csAsyncDns ) ;
  4998. IncAsyncDnsObjs();
  4999. BUMP_COUNTER(this, RoutingTableLookups);
  5000. // Insert into the list of connected outbound users.
  5001. InsertTailList( &m_AsyncDnsList, &pcc->QueryListEntry());
  5002. LeaveCriticalSection( &m_csAsyncDns ) ;
  5003. TraceFunctLeaveEx((LPARAM)this);
  5004. return TRUE;
  5005. }
  5006. VOID SMTP_SERVER_INSTANCE::RemoveAsyncDnsObject( IN OUT CAsyncSmtpDns * pConn)
  5007. {
  5008. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::RemoveAsyncDnsObject");
  5009. _ASSERT( pConn != NULL);
  5010. EnterCriticalSection( &m_csAsyncDns ) ;
  5011. // Remove from list of connections
  5012. RemoveEntryList( &pConn->QueryListEntry());
  5013. DecAsyncDnsObjs();
  5014. DROP_COUNTER(this, RoutingTableLookups);
  5015. LeaveCriticalSection( &m_csAsyncDns ) ;
  5016. TraceFunctLeaveEx((LPARAM)this);
  5017. } // SMTP_SERVER_INSTANCE::RemoveAsyncObject()
  5018. VOID SMTP_SERVER_INSTANCE::DisconnectAllAsyncDnsConnections( VOID)
  5019. {
  5020. int iteration = 0;
  5021. int i = 0;
  5022. int Count = 0;
  5023. DWORD dwLastAllocCount = 0;
  5024. DWORD dwAllocCount;
  5025. int AfterSleepCount = 0;
  5026. DWORD dwStopHint = 2;
  5027. DWORD dwTickCount;
  5028. DWORD dwError = 0;
  5029. PLIST_ENTRY pEntry = NULL;
  5030. CAsyncSmtpDns * pConn = NULL;
  5031. TraceFunctEnter("SMTP_SERVER_INSTANCE::DisconnectAllAsyncDnsConnections( VOID)");
  5032. if (m_fShutdownCalled) {
  5033. DebugTrace((LPARAM)this, "m_fShutdownCalled already -- leaving");
  5034. TraceFunctLeaveEx((LPARAM) this);
  5035. }
  5036. EnterCriticalSection( &m_csAsyncDns ) ;
  5037. //close down all the active sockets.
  5038. for ( pEntry = m_AsyncDnsList.Flink; pEntry != &m_AsyncDnsList; pEntry = pEntry->Flink) {
  5039. //get the next connection object
  5040. pConn = (CAsyncSmtpDns *) CONTAINING_RECORD( pEntry, CAsyncSmtpDns, m_ListEntry);
  5041. _ASSERT( pConn != NULL);
  5042. //call the disconnect routine. DisconnectClient() just closes the socket.
  5043. //This will cause all pending I/Os to fail, and have the connections
  5044. //"bubble up to the completion routine where they will be removed from
  5045. //the connection list and then distroyed
  5046. pConn->DisconnectClient();
  5047. }
  5048. LeaveCriticalSection( &m_csAsyncDns ) ;
  5049. //
  5050. // Wait for the users to die.
  5051. // The connection objects should be automatically freed because the
  5052. // socket has been closed. Subsequent requests will fail
  5053. // and cause a blowaway of the connection objects.
  5054. // looping is used to get out as early as possible when m_cCurrentConn == 0
  5055. //
  5056. //
  5057. // need to check Pool.GetAllocCount instead of InUseList.Empty
  5058. // because alloc goes to zero during the delete operator
  5059. // instead of during the destructor
  5060. //
  5061. // We sleep at most 120 seconds for a fixed user count.
  5062. //
  5063. dwTickCount = GetTickCount();
  5064. for (i = 0; i < 500; i++) {
  5065. DebugTrace((LPARAM)this, "Waiting for connections to die, i = %u", i);
  5066. dwAllocCount = (DWORD) GetAsyncDnsAllocCount ();
  5067. if (dwAllocCount == 0) {
  5068. DebugTrace((LPARAM)this, "All SMTP DNS connections are gone!");
  5069. break;
  5070. }
  5071. Sleep(1000);
  5072. // Update the stop hint checkpoint when we get within 1 second (1000 ms), of the timeout...
  5073. if ((SERVICE_STOP_WAIT_HINT - 1000) < (GetTickCount() - dwTickCount) && g_pInetSvc &&
  5074. g_pInetSvc->QueryCurrentServiceState() == SERVICE_STOP_PENDING) {
  5075. DebugTrace((LPARAM)this, "Updating stop hint, checkpoint = %u", dwStopHint);
  5076. g_pInetSvc->UpdateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, dwStopHint,
  5077. SERVICE_STOP_WAIT_HINT ) ;
  5078. dwStopHint++ ;
  5079. dwTickCount = GetTickCount();
  5080. }
  5081. DebugTrace((LPARAM)this, "Alloc counts: current = %u, last = %u",
  5082. dwAllocCount, dwLastAllocCount);
  5083. if (dwAllocCount < dwLastAllocCount) {
  5084. DebugTrace((LPARAM)this, "SMTP DNS Connections are going away, reseting i");
  5085. i = 0;
  5086. }
  5087. dwLastAllocCount = dwAllocCount;
  5088. }
  5089. if (i == 500) {
  5090. ErrorTrace((LPARAM) this, "%d users won't die", m_cCurrentConnections);
  5091. //
  5092. // once we're thru do it again to find any stray clients
  5093. //
  5094. EnterCriticalSection( &m_csAsyncDns ) ;
  5095. for (pEntry = m_AsyncDnsList.Flink;
  5096. pEntry != &m_AsyncDnsList;
  5097. pEntry = pEntry->Flink ) {
  5098. //
  5099. // get the next connection object
  5100. //
  5101. pConn = (CAsyncSmtpDns *)CONTAINING_RECORD(pEntry, CAsyncSmtpDns, m_ListEntry);
  5102. _ASSERT(pConn != NULL);
  5103. ErrorTrace( (LPARAM)pConn, "Stray client" );
  5104. }
  5105. LeaveCriticalSection( &m_csAsyncDns ) ;
  5106. }
  5107. DebugTrace( (LPARAM)this, "SMTP DNS Count at end is: %d", CAsyncSmtpDns::Pool.GetAllocCount() );
  5108. TraceFunctLeaveEx((LPARAM) this);
  5109. }
  5110. BOOL SMTP_SERVER_INSTANCE::InsertAsyncObject( IN OUT CAsyncMx *pcc)
  5111. {
  5112. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::InsertNewAsyncConnection");
  5113. _ASSERT( pcc != NULL);
  5114. m_OutLock.ExclusiveLock();
  5115. IncAsyncMxOutObjs();
  5116. // Insert into the list of connected outbound users.
  5117. InsertTailList( &m_AsynConnectList, &pcc->QueryListEntry());
  5118. m_OutLock.ExclusiveUnlock();
  5119. TraceFunctLeaveEx((LPARAM)this);
  5120. return TRUE;
  5121. }
  5122. VOID SMTP_SERVER_INSTANCE::RemoveAsyncObject( IN OUT CAsyncMx * pConn)
  5123. {
  5124. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::RemoveAsyncObject");
  5125. _ASSERT( pConn != NULL);
  5126. m_OutLock.ExclusiveLock();
  5127. // Remove from list of connections
  5128. RemoveEntryList( &pConn->QueryListEntry());
  5129. DecAsyncMxOutObjs();
  5130. m_OutLock.ExclusiveUnlock();
  5131. TraceFunctLeaveEx((LPARAM)this);
  5132. } // SMTP_SERVER_INSTANCE::RemoveAsyncObject()
  5133. VOID SMTP_SERVER_INSTANCE::DisconnectAllAsyncConnections( VOID)
  5134. {
  5135. PLIST_ENTRY pEntry = NULL;
  5136. CAsyncMx * pConn = NULL;
  5137. int iteration = 0;
  5138. int i = 0;
  5139. int Count = 0;
  5140. LONG cLastThreadCount = 0;
  5141. DWORD dwLastAllocCount = 0;
  5142. DWORD dwAllocCount;
  5143. int AfterSleepCount = 0;
  5144. DWORD dwStopHint = 2;
  5145. DWORD dwTickCount;
  5146. DWORD dwError = 0;
  5147. TraceFunctEnter("SMTP_SERVER_INSTANCE::DisconnectAllAsynConnections( VOID)");
  5148. #if 0
  5149. //close down all the active sockets.
  5150. for ( pEntry = m_AsynConnectList.Flink; pEntry != &m_AsynConnectList; pEntry = pEntry->Flink) {
  5151. //get the next connection object
  5152. pConn = (CAsyncMx *) CONTAINING_RECORD( pEntry, CAsyncMx, m_ListEntry);
  5153. _ASSERT( pConn != NULL);
  5154. pConn->SignalObject( );
  5155. }
  5156. #endif
  5157. //
  5158. // Wait for the users to die.
  5159. // The connection objects should be automatically freed because the
  5160. // socket has been closed. Subsequent requests will fail
  5161. // and cause a blowaway of the connection objects.
  5162. // looping is used to get out as early as possible when m_cCurrentConn == 0
  5163. //
  5164. //
  5165. // need to check Pool.GetAllocCount instead of InUseList.Empty
  5166. // because alloc goes to zero during the delete operator
  5167. // instead of during the destructor
  5168. //
  5169. // We sleep at most 120 seconds for a fixed user count.
  5170. //
  5171. dwTickCount = GetTickCount();
  5172. for (i = 0; i < 500; i++) {
  5173. DebugTrace((LPARAM)this, "Waiting for async connections to die, i = %u", i);
  5174. dwAllocCount = (DWORD) GetAsyncMxOutAllocCount();
  5175. if (dwAllocCount == 0) {
  5176. DebugTrace((LPARAM)this, "All CASYNCMXs connections are gone!");
  5177. break;
  5178. }
  5179. Sleep(1000);
  5180. // Update the stop hint checkpoint when we get within 1 second (1000 ms), of the timeout...
  5181. if ((SERVICE_STOP_WAIT_HINT - 1000) < (GetTickCount() - dwTickCount) && g_pInetSvc &&
  5182. g_pInetSvc->QueryCurrentServiceState() == SERVICE_STOP_PENDING) {
  5183. DebugTrace((LPARAM)this, "Updating stop hint, checkpoint = %u", dwStopHint);
  5184. g_pInetSvc->UpdateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, dwStopHint,
  5185. SERVICE_STOP_WAIT_HINT ) ;
  5186. dwStopHint++ ;
  5187. dwTickCount = GetTickCount();
  5188. }
  5189. DebugTrace((LPARAM)this, "Alloc counts: current = %u, last = %u; Thread counts: current = %d, last = %d",
  5190. dwAllocCount, dwLastAllocCount, GetProcessClientThreads(), cLastThreadCount);
  5191. if (dwAllocCount < dwLastAllocCount) {
  5192. DebugTrace((LPARAM)this, "CASYNCMX Connections are going away, resetting i");
  5193. i = 0;
  5194. }
  5195. dwLastAllocCount = dwAllocCount;
  5196. }
  5197. if (i == 500) {
  5198. ErrorTrace((LPARAM) this, "%d users won't die", m_cNumAsyncObjsAlloced);
  5199. //
  5200. // once we're thru do it again to find any stray clients
  5201. //
  5202. m_OutLock.ExclusiveLock();
  5203. for (pEntry = m_ConnectionsList.Flink;
  5204. pEntry != &m_ConnectionsList;
  5205. pEntry = pEntry->Flink ) {
  5206. //
  5207. // get the next connection object
  5208. //
  5209. pConn = (CAsyncMx *)CONTAINING_RECORD(pEntry, CAsyncMx, m_ListEntry);
  5210. _ASSERT(pConn != NULL);
  5211. ErrorTrace( (LPARAM)pConn, "Stray client" );
  5212. }
  5213. m_OutLock.ExclusiveUnlock();
  5214. }
  5215. DebugTrace( (LPARAM)this, "CASYNCMX Count at end is: %d", m_cNumAsyncObjsAlloced);
  5216. TraceFunctLeaveEx((LPARAM) this);
  5217. }
  5218. /*++
  5219. Disconnects all user connections.
  5220. --*/
  5221. VOID SMTP_SERVER_INSTANCE::DisconnectAllOutboundConnections( VOID)
  5222. {
  5223. int iteration = 0;
  5224. int i = 0;
  5225. int Count = 0;
  5226. DWORD dwLastAllocCount = 0;
  5227. DWORD dwAllocCount;
  5228. int AfterSleepCount = 0;
  5229. DWORD dwStopHint = 2;
  5230. DWORD dwTickCount;
  5231. PLIST_ENTRY pEntry = NULL;
  5232. CLIENT_CONNECTION * pConn = NULL;
  5233. TraceFunctEnterEx((LPARAM)this, "SMTP_SERVER_INSTANCE::DisconnectAllOutboundConnections( VOID)");
  5234. if (m_fShutdownCalled) {
  5235. DebugTrace((LPARAM)this, "m_fShutdownCalled already -- leaving");
  5236. TraceFunctLeaveEx((LPARAM) this);
  5237. }
  5238. m_OutLock.ExclusiveLock();
  5239. //close down all the active sockets.
  5240. for ( pEntry = m_OutConnectionsList.Flink; pEntry != &m_OutConnectionsList; pEntry = pEntry->Flink) {
  5241. //get the next connection object
  5242. pConn = CONTAINING_RECORD( pEntry, CLIENT_CONNECTION, m_listEntry);
  5243. _ASSERT( pConn != NULL);
  5244. //call the disconnect routine. DisconnectClient() just closes the socket.
  5245. //This will cause all pending I/Os to fail, and have the connections
  5246. //"bubble up to the completion routine where they will be removed from
  5247. //the connection list and then distroyed
  5248. pConn->DisconnectClient( ERROR_SERVER_DISABLED);
  5249. }
  5250. m_OutLock.ExclusiveUnlock();
  5251. //
  5252. // Wait for the users to die.
  5253. // The connection objects should be automatically freed because the
  5254. // socket has been closed. Subsequent requests will fail
  5255. // and cause a blowaway of the connection objects.
  5256. // looping is used to get out as early as possible when m_cCurrentConn == 0
  5257. //
  5258. //
  5259. // Wait for the users to die.
  5260. // The connection objects should be automatically freed because the
  5261. // socket has been closed. Subsequent requests will fail
  5262. // and cause a blowaway of the connection objects.
  5263. // looping is used to get out as early as possible when m_cCurrentConn == 0
  5264. //
  5265. //
  5266. // need to check Pool.GetAllocCount instead of InUseList.Empty
  5267. // because alloc goes to zero during the delete operator
  5268. // instead of during the destructor
  5269. //
  5270. // We sleep at most 180 seconds for a fixed user count.
  5271. //
  5272. dwTickCount = GetTickCount();
  5273. for (i = 0; i < 180; i++) {
  5274. DebugTrace((LPARAM)this, "Waiting for connections to die, i = %u", i);
  5275. dwAllocCount = (DWORD) GetConnOutAllocCount();
  5276. if (dwAllocCount == 0) {
  5277. DebugTrace((LPARAM)this, "All SMTP_CONNOUTs connections are gone!");
  5278. break;
  5279. }
  5280. Sleep(1000);
  5281. // Update the stop hint checkpoint when we get within 1 second (1000 ms), of the timeout...
  5282. if ((SERVICE_STOP_WAIT_HINT - 1000) < (GetTickCount() - dwTickCount) && g_pInetSvc &&
  5283. g_pInetSvc->QueryCurrentServiceState() == SERVICE_STOP_PENDING) {
  5284. DebugTrace((LPARAM)this, "Updating stop hint, checkpoint = %u", dwStopHint);
  5285. g_pInetSvc->UpdateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, dwStopHint,
  5286. SERVICE_STOP_WAIT_HINT ) ;
  5287. dwStopHint++ ;
  5288. dwTickCount = GetTickCount();
  5289. }
  5290. DebugTrace((LPARAM)this, "Alloc counts: current = %u, last = %u", dwAllocCount, dwLastAllocCount);
  5291. if (dwAllocCount < dwLastAllocCount) {
  5292. DebugTrace((LPARAM)this, "SMTP_CONNECTION Connections are going away, resetting i");
  5293. i = 0;
  5294. }
  5295. dwLastAllocCount = dwAllocCount;
  5296. }
  5297. DebugTrace( (LPARAM)this, "SMTP_CONNOUT Count at end is: %d", SMTP_CONNECTION::Pool.GetAllocCount() );
  5298. TraceFunctLeaveEx((LPARAM)this);
  5299. }
  5300. /*++
  5301. Removes the current connection from the list of conenctions
  5302. and decrements count of connected users
  5303. Arguments:
  5304. pcc pointer to client connection to be removed
  5305. --*/
  5306. VOID SMTP_SERVER_INSTANCE::RemoveOutboundConnection( IN OUT CLIENT_CONNECTION * pConn)
  5307. {
  5308. _ASSERT( pConn != NULL);
  5309. m_OutLock.ExclusiveLock();
  5310. // Remove from list of connections
  5311. RemoveEntryList( &pConn->QueryListEntry());
  5312. // Decrement count of current users
  5313. m_cCurrentOutConnections--;
  5314. BUMP_COUNTER(this, NumConnOutClose);
  5315. m_OutLock.ExclusiveUnlock();
  5316. } // SMTP_SERVER_INSTANCE::RemoveConnection()
  5317. BOOL SMTP_SERVER_INSTANCE::InitDirectoryNotification(void)
  5318. {
  5319. char MailPickUp[MAX_PATH + 1];
  5320. TraceFunctEnterEx((LPARAM)this, "InitDirectoryNotification");
  5321. lstrcpy(MailPickUp, GetMailPickupDir());
  5322. //get rid of the \\ at the end of the name
  5323. if (MailPickUp [GetMailPickupDirLength() - 1] == '\\')
  5324. MailPickUp [GetMailPickupDirLength() - 1] = '\0';
  5325. //create an outbound connectiong_SmtpConfig->GetMailPickupDir()
  5326. SmtpDir = SMTP_DIRNOT::CreateSmtpDirNotification(MailPickUp, SMTP_DIRNOT::ReadDirectoryCompletion, this);
  5327. if (SmtpDir == NULL) {
  5328. TraceFunctLeaveEx((LPARAM)this);
  5329. return FALSE;
  5330. }
  5331. //now that both queues are initialized, create the
  5332. //thread that goes off and finds any mail files
  5333. //that were not sent and builds up both queues
  5334. DWORD ThreadId;
  5335. DWORD error;
  5336. DirPickupThreadHandle = CreateThread (NULL, 0, SMTP_DIRNOT::PickupInitialFiles, SmtpDir, 0, &ThreadId);
  5337. if (DirPickupThreadHandle == NULL) {
  5338. error = GetLastError();
  5339. ErrorTrace((LPARAM)this, "CreateThread failed for SMTP_DIRNOT::PickupInitialFiles. err: %u", error);
  5340. }
  5341. TraceFunctLeaveEx((LPARAM)this);
  5342. return TRUE;
  5343. }
  5344. void SMTP_SERVER_INSTANCE::DestroyDirectoryNotification(void)
  5345. {
  5346. TraceFunctEnterEx((LPARAM)this, "DestroyDirectoryNotification(void)");
  5347. //wait for the initial pickup thread
  5348. //to die
  5349. if (DirPickupThreadHandle != NULL) {
  5350. if (SmtpDir)
  5351. SmtpDir->SetPickupRetryQueueEvent();
  5352. WaitForSingleObject(DirPickupThreadHandle, INFINITE);
  5353. ErrorTrace((LPARAM)this, "Initial pickup thread is dead");
  5354. CloseHandle(DirPickupThreadHandle);
  5355. DirPickupThreadHandle = NULL;
  5356. }
  5357. //Just close the handle to the
  5358. //directory. This will cause
  5359. //the notification to come back
  5360. //with an error, and it will be
  5361. //deleted.
  5362. if (SmtpDir) {
  5363. SmtpDir->CloseDirHandle();
  5364. }
  5365. if (SmtpDir) {
  5366. delete SmtpDir;
  5367. SmtpDir = NULL;
  5368. CloseHandle(StopHandle);
  5369. StopHandle = NULL;
  5370. }
  5371. TraceFunctLeaveEx((LPARAM)this);
  5372. }
  5373. extern char g_UserName[];
  5374. extern char g_DomainName[];
  5375. extern char g_Password[];
  5376. void SMTP_SERVER_INSTANCE::SinkSmtpServerStartHintFunc(void)
  5377. {
  5378. if (g_pInetSvc) {
  5379. ((PSMTP_IIS_SERVICE) g_pInetSvc)->StartHintFunction();
  5380. }
  5381. }
  5382. void SMTP_SERVER_INSTANCE::SinkSmtpServerStopHintFunc(void)
  5383. {
  5384. StopHint();
  5385. }
  5386. void SmtpServerStartHintFunc(PVOID ThisPtr)
  5387. {
  5388. ((PSMTP_IIS_SERVICE) g_pInetSvc)->StartHintFunction();
  5389. }
  5390. void SmtpServerStopHintFunc(PVOID ThisPtr)
  5391. {
  5392. ((SMTP_SERVER_INSTANCE *) ThisPtr)->StopHint();
  5393. }
  5394. BOOL SMTP_SERVER_INSTANCE::StartAdvancedQueueing(void)
  5395. {
  5396. TraceFunctEnterEx((LPARAM) this, "LoadAdvancedQueueing");
  5397. HRESULT hr = S_OK;
  5398. ((PSMTP_IIS_SERVICE) g_pInetSvc)->StartHintFunction();
  5399. hr = (g_pfnInitializeAQ)(m_ComSmtpServer, QueryInstanceId(),
  5400. g_UserName, g_DomainName, g_Password, SmtpServerStartHintFunc,
  5401. (PVOID) this, &m_IAQ, &m_ICM,
  5402. &m_pIAdvQueueConfig, &m_pvAQInstanceContext);
  5403. ErrorTrace((LPARAM)this, "Advanced Queuing returned status code %x", hr);
  5404. TraceFunctLeaveEx((LPARAM) this);
  5405. return !FAILED(hr);
  5406. }
  5407. BOOL SMTP_SERVER_INSTANCE::StopQDrivers(void)
  5408. {
  5409. TraceFunctEnterEx((LPARAM) this, "StopQDrivers");
  5410. if (m_pIAdvQueueConfig) {
  5411. m_pIAdvQueueConfig->Release();
  5412. m_pIAdvQueueConfig = NULL;
  5413. }
  5414. if (m_IAQ != NULL) {
  5415. m_IAQ->Release();
  5416. m_IAQ = NULL;
  5417. }
  5418. if (m_ICM != NULL) {
  5419. m_ICM->Release();
  5420. m_ICM = NULL;
  5421. }
  5422. if (fInitializedAQ && g_pfnDeinitializeAQ && m_pvAQInstanceContext) {
  5423. (g_pfnDeinitializeAQ)(m_pvAQInstanceContext, SmtpServerStopHintFunc, (PVOID) this);
  5424. m_pvAQInstanceContext = NULL;
  5425. fInitializedAQ = FALSE;
  5426. }
  5427. TraceFunctLeaveEx((LPARAM) this);
  5428. return TRUE;
  5429. }
  5430. extern void VerifyFQDNWithGlobalIp(DWORD InstanceId,char * szFQDomainName);
  5431. void SMTP_SERVER_INSTANCE::VerifyFQDNWithBindings(void)
  5432. {
  5433. CONST CHAR *apszMsgs[2];
  5434. CHAR achInstance[20];
  5435. CHAR achIPAddr[20];
  5436. char * FQDNValue = NULL;
  5437. char * IpAddress = NULL;
  5438. in_addr UNALIGNED * P_Addr = NULL;
  5439. PHOSTENT pH = NULL;
  5440. char * Ptr = NULL;
  5441. const char * StartPtr = NULL;
  5442. const CHAR * ipAddressString = NULL;
  5443. const CHAR * ipPortString = NULL;
  5444. const CHAR * end = NULL;
  5445. DWORD InetAddr = 0;
  5446. DWORD CharIpSize = 0;
  5447. CHAR temp[sizeof("123.123.123.123")];
  5448. INT length;
  5449. BOOL fGlobalListChecked = FALSE;
  5450. //Get the current instnace id
  5451. wsprintf( achInstance,
  5452. "%lu",
  5453. QueryInstanceId() );
  5454. apszMsgs[1] = achInstance;
  5455. //grab the sharing lock
  5456. if (m_ServerBindings.IsEmpty()) {
  5457. if (!fGlobalListChecked) {
  5458. VerifyFQDNWithGlobalIp(QueryInstanceId(), m_szFQDomainName);
  5459. fGlobalListChecked = TRUE;
  5460. }
  5461. } else {
  5462. for (StartPtr = m_ServerBindings.First(); StartPtr != NULL; StartPtr = m_ServerBindings.Next( StartPtr )) {
  5463. ipAddressString = StartPtr;
  5464. ipPortString = strchr(StartPtr, ':');
  5465. if (ipPortString == NULL) {
  5466. wsprintf( achIPAddr,"%s","0.0.0.0");
  5467. apszMsgs[0] = achIPAddr;
  5468. SmtpLogEvent( SMTP_EVENT_UNRESOLVED_FQDN,2,apszMsgs,0 );
  5469. }
  5470. // Validate and parse the IP address portion.
  5471. //
  5472. if ( *ipAddressString == ':' ) {
  5473. if (!fGlobalListChecked) {
  5474. VerifyFQDNWithGlobalIp(QueryInstanceId(),m_szFQDomainName);
  5475. fGlobalListChecked = TRUE;
  5476. }
  5477. } else {
  5478. length = DIFF(ipPortString - ipAddressString) - 1;
  5479. if ( length > sizeof(temp) ) {
  5480. wsprintf( achIPAddr,"%s", temp);
  5481. apszMsgs[0] = achIPAddr;
  5482. SmtpLogEvent( SMTP_EVENT_UNRESOLVED_FQDN,1,apszMsgs,0 );
  5483. }
  5484. CopyMemory( temp, ipAddressString, length);
  5485. temp[length] = '\0';
  5486. InetAddr = inet_addr( temp );
  5487. if ( InetAddr != INADDR_NONE ) {
  5488. //For IP address find the host name
  5489. ((PSMTP_IIS_SERVICE) g_pInetSvc)->StartHintFunction();
  5490. pH = gethostbyaddr((char*)(&InetAddr), 4, PF_INET );
  5491. if (pH && pH->h_name) {
  5492. if (_strcmpi(pH->h_name,m_szFQDomainName)) {
  5493. wsprintf( achIPAddr,"%s",temp);
  5494. apszMsgs[0] = achIPAddr;
  5495. SmtpLogEvent( SMTP_EVENT_UNRESOLVED_FQDN,2,apszMsgs,0 );
  5496. }
  5497. } else {
  5498. wsprintf( achIPAddr,"%s",temp);
  5499. apszMsgs[0] = achIPAddr;
  5500. SmtpLogEvent( SMTP_EVENT_UNRESOLVED_FQDN,2,apszMsgs,0 );
  5501. }
  5502. } else {
  5503. wsprintf( achIPAddr,"%s", temp);
  5504. apszMsgs[0] = achIPAddr;
  5505. SmtpLogEvent( SMTP_EVENT_UNRESOLVED_FQDN,2,apszMsgs,0 );
  5506. }
  5507. }//end else of if( *ipAddressString == ':' )
  5508. }//end for
  5509. }//end else
  5510. return;
  5511. }
  5512. BOOL SMTP_SERVER_INSTANCE::RegisterServicePrincipalNames(BOOL fLock)
  5513. {
  5514. if (fLock)
  5515. m_GenLock.ExclusiveLock();
  5516. if (!m_fHaveRegisteredPrincipalNames) {
  5517. PSMTP_IIS_SERVICE pService = (PSMTP_IIS_SERVICE) g_pInetSvc;
  5518. if (pService->ResetServicePrincipalNames()) {
  5519. m_fHaveRegisteredPrincipalNames =
  5520. CSecurityCtx::RegisterServicePrincipalNames(
  5521. SMTP_SERVICE_NAME, m_szFQDomainName);
  5522. }
  5523. }
  5524. if (fLock)
  5525. m_GenLock.ExclusiveUnlock();
  5526. return( m_fHaveRegisteredPrincipalNames );
  5527. }
  5528. //+------------------------------------------------------------
  5529. //
  5530. // Function: SMTP_SERVER_INSTANCE::HrSetWellKnownIServerProps
  5531. //
  5532. // Synopsis: Take info from member variables and set them in the
  5533. // IServer property bag
  5534. //
  5535. // Arguments: NONE
  5536. //
  5537. // Returns:
  5538. // S_OK: Success
  5539. // error from CMailMsgLoggingPropertyBag
  5540. //
  5541. // History:
  5542. // jstamerj 1998/11/17 16:41:08: Created.
  5543. //
  5544. //-------------------------------------------------------------
  5545. HRESULT SMTP_SERVER_INSTANCE::HrSetWellKnownIServerProps()
  5546. {
  5547. HRESULT hr;
  5548. TraceFunctEnterEx((LPARAM)this,
  5549. "SMTP_SERVER_INSTANCE::HrSetWellKnownIServerProps");
  5550. _ASSERT(m_pSmtpInfo);
  5551. hr = m_InstancePropertyBag.PutDWORD(
  5552. PE_ISERVID_DW_INSTANCE,
  5553. m_pSmtpInfo->dwInstanceId);
  5554. if(FAILED(hr))
  5555. goto CLEANUP;
  5556. hr = m_InstancePropertyBag.PutStringA(
  5557. PE_ISERVID_SZ_DEFAULTDOMAIN,
  5558. m_szDefaultDomain);
  5559. if(FAILED(hr))
  5560. goto CLEANUP;
  5561. CLEANUP:
  5562. DebugTrace((LPARAM)this, "returning hr %08lx", hr);
  5563. TraceFunctLeaveEx((LPARAM)this);
  5564. return hr;
  5565. }
  5566. //---[ SMTP_SERVER_INSTANCE::IsDropDirQuotaExceeded ]--------------------------
  5567. //
  5568. //
  5569. // Description:
  5570. // Checks to see if we are past our drop dir quota (if enforced). The
  5571. // quota is defined to be 11 times the max messages size (or 22 MB if
  5572. // there is no max message size). If we are within 1 max message size
  5573. // of the quota (2MB is no max message size), we will assume that this
  5574. // message will push us over the quota.
  5575. // Parameters:
  5576. // -
  5577. // Returns:
  5578. // TRUE We are past our quota (or this message will do it)
  5579. // FALSE We are still under drop dir quota.
  5580. // History:
  5581. // 10/28/1999 - MikeSwa Created
  5582. //
  5583. //-----------------------------------------------------------------------------
  5584. BOOL SMTP_SERVER_INSTANCE::IsDropDirQuotaExceeded()
  5585. {
  5586. TraceFunctEnterEx((LPARAM) this, "SMTP_SERVER_INSTANCE::IsDropDirQuotaExceeded");
  5587. DWORD cbMaxMsgSize = GetMaxMsgSize();
  5588. BOOL fQuotaExceeded = FALSE;
  5589. HANDLE hDropDirFind = INVALID_HANDLE_VALUE;
  5590. LARGE_INTEGER LIntDropDirSize;
  5591. LARGE_INTEGER LIntDropQuota;
  5592. LARGE_INTEGER LIntCurrentFile;
  5593. WIN32_FIND_DATA FileInfo;
  5594. CHAR szDropDirSearch[sizeof(m_szMailDropDir) + sizeof("*")];
  5595. ZeroMemory(&FileInfo, sizeof(FileInfo));
  5596. LIntDropDirSize.QuadPart = 0;
  5597. LIntDropQuota.QuadPart = 0;
  5598. if (!IsDropDirQuotaCheckingEnabled() || !GetMailDropDir(szDropDirSearch))
  5599. {
  5600. fQuotaExceeded = FALSE;
  5601. goto Exit;
  5602. }
  5603. if (!cbMaxMsgSize)
  5604. cbMaxMsgSize = 2*1024*1024; //Default to 2 MB
  5605. //Set drop dir quota to be 10 times the max message size, if we
  5606. //exceed this, then we are within 1 max message size of the "true" quota
  5607. LIntDropQuota.QuadPart = 10*cbMaxMsgSize;
  5608. //Build up a search so we can loop over the file names
  5609. lstrcat(szDropDirSearch, "*");
  5610. hDropDirFind = FindFirstFileEx(szDropDirSearch,
  5611. FindExInfoStandard,
  5612. &FileInfo,
  5613. FindExSearchNameMatch,
  5614. NULL,
  5615. 0);
  5616. if (INVALID_HANDLE_VALUE == hDropDirFind)
  5617. {
  5618. ErrorTrace((LPARAM) this,
  5619. "Unable to open drop dir for quota checking - 0x%X", GetLastError());
  5620. //If we cannot open the directory assume we are over quota
  5621. fQuotaExceeded = TRUE;
  5622. goto Exit;
  5623. }
  5624. //Loop over all the files we have found
  5625. do
  5626. {
  5627. LIntCurrentFile.LowPart = FileInfo.nFileSizeLow;
  5628. LIntCurrentFile.HighPart = FileInfo.nFileSizeHigh;
  5629. LIntDropDirSize.QuadPart += LIntCurrentFile.QuadPart;
  5630. if (LIntDropQuota.QuadPart <= LIntDropDirSize.QuadPart)
  5631. {
  5632. fQuotaExceeded = TRUE;
  5633. goto Exit;
  5634. }
  5635. } while (FindNextFile(hDropDirFind, &FileInfo));
  5636. if (LIntDropQuota.QuadPart <= LIntDropDirSize.QuadPart)
  5637. fQuotaExceeded = TRUE;
  5638. else
  5639. fQuotaExceeded = FALSE;
  5640. Exit:
  5641. if (INVALID_HANDLE_VALUE != hDropDirFind)
  5642. FindClose(hDropDirFind);
  5643. TraceFunctLeave();
  5644. return fQuotaExceeded;
  5645. }