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.

344 lines
12 KiB

  1. #include "stdafx.h"
  2. #include "exchange.hpp"
  3. #include "common.hpp"
  4. #include "err.hpp"
  5. #include "ErrDct.hpp"
  6. #include "UString.hpp"
  7. #include "sidcache.hpp"
  8. #include "sd.hpp"
  9. #include "SecObj.hpp"
  10. #include "exldap.h"
  11. #include "Mcs.h"
  12. #include "folders.h"
  13. #include "treg.hpp"
  14. using namespace nsFolders;
  15. extern TErrorDct err;
  16. #define NOT_PT_ERROR(x) ( PROP_TYPE(x.ulPropTag) != PT_ERROR )
  17. #define LDAP_PortNumber_DN_Part L"/cn=Protocols/cn=LDAP"
  18. #define ATT_OBJ_CLASS L"Obj-Class"
  19. #define ATT_DIST_NAME L"Obj-Dist-Name"
  20. #define ATT_LDAP_PORT L"Port-Number"
  21. #define LDAP_USE_SITE_VALUES L"Use-Site-Values"
  22. TGlobalDirectory::TGlobalDirectory()
  23. {
  24. m_stat = NULL;
  25. }
  26. TGlobalDirectory::~TGlobalDirectory()
  27. {
  28. }
  29. #define NDX_SID 3
  30. #define NDX_SD 4
  31. void
  32. TGlobalDirectory::GetSiteNameForServer(
  33. WCHAR const * server, // in - name of exchange server to use
  34. CLdapEnum * e, // in - LDAP connection to use for query
  35. WCHAR * siteName // out- distinguished name of exchange site for server
  36. )
  37. {
  38. WCHAR * atts[6] = { L"distinguishedName", L"rdn",NULL };
  39. WCHAR query[200];
  40. DWORD rc;
  41. WCHAR ** values = NULL;
  42. siteName[0] = 0;
  43. swprintf(query,L"(&(objectClass=computer)(rdn=%ls))",server);
  44. rc = e->Open(query,L"",2,100,3,atts);
  45. // there should be only one server with this name
  46. if (! rc )
  47. rc = e->Next(&values);
  48. if (! rc )
  49. {
  50. if ( !UStrICmp(values[1],server) )
  51. {
  52. WCHAR serverPrefix[LEN_Path];
  53. _snwprintf(serverPrefix,DIM(serverPrefix),L"cn=%ls,cn=Servers,cn=Configuration,",values[1]);
  54. serverPrefix[DIM(serverPrefix) - 1] = L'\0';
  55. if ( ! UStrICmp(values[0],serverPrefix,UStrLen(serverPrefix)) )
  56. {
  57. UStrCpy(siteName,values[0] + UStrLen(serverPrefix),LEN_Path);
  58. }
  59. else
  60. {
  61. err.MsgWrite(ErrE,DCT_MSG_GENERIC_S,values[0]);
  62. }
  63. }
  64. else
  65. {
  66. err.MsgWrite(ErrE,DCT_MSG_LDAP_CALL_FAILED_SD,server,ERROR_NOT_FOUND);
  67. }
  68. e->FreeData(values);
  69. }
  70. else
  71. {
  72. err.SysMsgWrite(ErrE,e->m_connection.LdapMapErrorToWin32(rc),DCT_MSG_LDAP_CALL_FAILED_SD,server,rc);
  73. }
  74. }
  75. BOOL
  76. TGlobalDirectory::DoLdapTranslation(
  77. WCHAR * server,
  78. WCHAR * domain,
  79. WCHAR * user,
  80. WCHAR * password,
  81. SecurityTranslatorArgs * args,
  82. WCHAR * basept,
  83. WCHAR * query
  84. )
  85. {
  86. CLdapEnum e;
  87. WCHAR * atts[6] = { L"distinguishedName", L"rdn", L"cn", L"Assoc-NT-Account",L"NT-Security-Descriptor",NULL };
  88. WCHAR ** values = NULL;
  89. DWORD ldapPort, sslPort;
  90. GetLDAPPort(&ldapPort, &sslPort);
  91. ULONG pageSize = 100;
  92. WCHAR basepoint[LEN_Path] = L"";
  93. e.m_connection.SetCredentials(domain,user,password);
  94. BOOL sslEnabled = FALSE;
  95. SetLastError(0);
  96. // try SSL port first
  97. DWORD rc = e.InitSSLConnection(server,&sslEnabled,sslPort);
  98. if (rc || sslEnabled == FALSE)
  99. {
  100. WCHAR* serverName = (server == NULL) ? L"" : server;
  101. if (rc == 0)
  102. err.MsgWrite(ErrW, DCT_MSG_CANNOT_ESTABLISH_SSL_CONNECTION_WITH_EXCHANGE_SERVER_WITHOUT_RC_SD, serverName, sslPort);
  103. else
  104. err.SysMsgWrite(ErrW, rc, DCT_MSG_CANNOT_ESTABLISH_SSL_CONNECTION_WITH_EXCHANGE_SERVER_WITH_RC_SDD, serverName, sslPort,rc);
  105. err.MsgWrite(ErrI, DCT_MSG_USE_REGULAR_PORT_DS, ldapPort, serverName);
  106. rc = e.InitConnection(server, ldapPort);
  107. }
  108. BOOL anychange = FALSE;
  109. BOOL verbose = args->LogVerbose();
  110. BOOL bUseMapFile = args->UsingMapFile();
  111. if (! rc )
  112. {
  113. if ( ! basept )
  114. {
  115. GetSiteNameForServer(server,&e,basepoint);
  116. }
  117. else
  118. {
  119. // use the user-specified basepoint
  120. safecopy(basepoint,basept);
  121. }
  122. if ( query )
  123. {
  124. rc = e.Open(query,basepoint,2,pageSize,5,atts);
  125. }
  126. else
  127. {
  128. rc = e.Open(L"(objectClass=*)",basepoint,2,pageSize,5,atts);
  129. }
  130. if ( ! rc )
  131. {
  132. do
  133. {
  134. rc = e.Next(&values);
  135. anychange = FALSE;
  136. if (! rc )
  137. {
  138. if ( args->Cache()->IsCancelled() )
  139. {
  140. err.MsgWrite(0,DCT_MSG_OPERATION_ABORTED);
  141. return FALSE;
  142. }
  143. if ( m_stat )
  144. {
  145. m_stat->DisplayPath(values[0]);
  146. m_stat->IncrementExamined(mailbox);
  147. }
  148. // update the Assoc-NT-Account, if any
  149. if ( values[NDX_SID] && *values[NDX_SID] )
  150. {
  151. // convert the SID to a binary value and look it up in the cache
  152. BYTE pSid[500];
  153. if ( e.m_connection.StringToBytes(values[NDX_SID],pSid) )
  154. {
  155. // check if the sid is one we need to change
  156. //TRACE (_T("DisplayName = %s "),pUserProperties[0].Value.lpszW);
  157. PSID newSid = 0;
  158. TAcctNode * node;
  159. if ( IsValidSid(pSid) )
  160. {
  161. if (!bUseMapFile)
  162. node = args->Cache()->Lookup(pSid);
  163. else
  164. node = args->Cache()->LookupWODomain(pSid);
  165. if ( m_stat )
  166. {
  167. m_stat->IncrementOwnerExamined();
  168. if ( verbose )
  169. err.MsgWrite(0,DCT_MSG_EXAMINED_S,values[0]);
  170. }
  171. if ( node == (TAcctNode*)-1 && m_stat )
  172. m_stat->IncrementOwnerNoTarget();
  173. if ( node && (node != (TAcctNode *)-1) && node->IsValidOnTgt() )
  174. {
  175. if (!bUseMapFile)
  176. newSid = args->Cache()->GetTgtSid(node);
  177. else
  178. newSid = args->Cache()->GetTgtSidWODomain(node);
  179. }
  180. else
  181. {
  182. newSid = NULL;
  183. m_stat->IncrementOwnerNoTarget();
  184. }
  185. }
  186. else
  187. {
  188. newSid = NULL;
  189. }
  190. if ( newSid )
  191. {
  192. //TRACE (_T("needs to be translated\n"));
  193. MCSASSERT ( IsValidSid(newSid) );
  194. WCHAR newSidStr[1000];
  195. if ( e.m_connection.BytesToString((BYTE*)newSid,newSidStr,GetLengthSid(newSid)) )
  196. {
  197. if ( !args->NoChange() )
  198. {
  199. rc = e.m_connection.UpdateSimpleStringValue(values[0],atts[NDX_SID],newSidStr);
  200. if ( rc )
  201. {
  202. err.SysMsgWrite(ErrE,rc,DCT_MSG_UPDATE_ACCOUNT_FAILED_D, rc);
  203. }
  204. else
  205. anychange = TRUE;
  206. }
  207. if ( anychange && m_stat )
  208. {
  209. m_stat->IncrementOwnerChange(node,mailbox,NULL);
  210. }
  211. }
  212. }
  213. }
  214. }
  215. // this variable determines whether we should continue mailbox translation
  216. DWORD dwContinueRC = ERROR_SUCCESS;
  217. // Update the NT-Security-Descriptor, if any
  218. // however, we do not try to roll back if anything wrong happens in this part
  219. if ( values[NDX_SD] && *values[NDX_SD] )
  220. {
  221. // convert the SID to a binary value and look it up in the cache
  222. BYTE * pSD = new BYTE[UStrLen(values[NDX_SD])];
  223. if (!pSD)
  224. dwContinueRC = ERROR_OUTOFMEMORY;
  225. if ( dwContinueRC == ERROR_SUCCESS && e.m_connection.StringToBytes(values[NDX_SD],pSD) )
  226. {
  227. TMapiSD tMailbox((SECURITY_DESCRIPTOR *)pSD);
  228. if ( tMailbox.HasSecurity() )
  229. {
  230. TSD * pSD = tMailbox.GetSecurity();
  231. bool changes = tMailbox.ResolveSDInternal(args->Cache(),m_stat,verbose,args->TranslationMode(),mailbox, bUseMapFile);
  232. if ( changes )
  233. {
  234. SECURITY_DESCRIPTOR * pRelSD = (SECURITY_DESCRIPTOR *)pSD->MakeRelSD();
  235. if (pRelSD == NULL)
  236. dwContinueRC = ERROR_OUTOFMEMORY;
  237. if ( dwContinueRC == ERROR_SUCCESS && ! args->NoChange() )
  238. {
  239. DWORD dwSDLength = GetSecurityDescriptorLength(pRelSD);
  240. WCHAR * pSDString = new WCHAR[1 + dwSDLength * 2];
  241. if (!pSDString)
  242. dwContinueRC = ERROR_OUTOFMEMORY;
  243. if ( dwContinueRC == ERROR_SUCCESS && e.m_connection.BytesToString((BYTE*)pRelSD,pSDString,dwSDLength) )
  244. {
  245. rc = e.m_connection.UpdateSimpleStringValue(values[0],atts[NDX_SD],pSDString);
  246. if ( rc )
  247. {
  248. err.SysMsgWrite(ErrE,rc,DCT_MSG_RECIP_SD_WRITE_FAILED_SD,values[0],rc);
  249. if ( rc == ERROR_INVALID_PARAMETER )
  250. {
  251. // this error occurs when the security descriptor is too large
  252. // don't abort in this case
  253. rc = 0;
  254. }
  255. }
  256. else
  257. anychange = TRUE;
  258. }
  259. delete [] pSDString;
  260. }
  261. if (pRelSD)
  262. free(pRelSD);
  263. }
  264. }
  265. }
  266. delete [] pSD;
  267. }
  268. if ( anychange && m_stat )
  269. {
  270. m_stat->IncrementChanged(mailbox);
  271. err.MsgWrite(0, DCT_MSG_MAILBOX_HAS_BEEN_UPDATED_S, values[0]);
  272. }
  273. if (dwContinueRC != ERROR_SUCCESS)
  274. {
  275. if (anychange)
  276. err.SysMsgWrite(ErrE,dwContinueRC,DCT_MSG_MAILBOX_TRANSLATION_ABORTED_WITH_UPDATE_SD,values[0],dwContinueRC);
  277. else
  278. err.SysMsgWrite(ErrE,dwContinueRC,DCT_MSG_MAILBOX_TRANSLATION_ABORTED_SD,values[0],dwContinueRC);
  279. e.FreeData(values);
  280. return FALSE;
  281. }
  282. e.FreeData(values);
  283. }
  284. } while ( ! rc );
  285. }
  286. if ( rc && (rc != LDAP_COMPARE_FALSE) && (rc != ERROR_NOT_FOUND) )
  287. {
  288. err.SysMsgWrite(ErrE,e.m_connection.LdapMapErrorToWin32(rc),DCT_MSG_LDAP_CALL_FAILED_SD,server,rc);
  289. }
  290. }
  291. else
  292. {
  293. err.SysMsgWrite(ErrE,rc,DCT_MSG_CANNOT_CONNECT_TO_EXCHANGE_SERVER_SSD,server,domain,user,rc);
  294. }
  295. return rc;
  296. }