Leaked source code of windows server 2003
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.

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