PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/mojoPortal.Business/LdapHelper.cs

#
C# | 518 lines | 462 code | 37 blank | 19 comment | 26 complexity | c4218932e029a4a6a41bbb8860401667 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause, CPL-1.0, CC-BY-SA-3.0, GPL-2.0
  1. // Author: TJ Fontaine
  2. // Created: 2005-09-30
  3. // Last Modified: 2011-02-05
  4. //
  5. // The use and distribution terms for this software are covered by the
  6. // Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
  7. // which can be found in the file CPL.TXT at the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by
  9. // the terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. // 2011-02-05 added changes from Jamie Eubanks to better support Active Directory
  13. using System;
  14. using System.Configuration;
  15. using Mono.Security.X509;
  16. using log4net;
  17. using Novell.Directory.Ldap;
  18. using System.DirectoryServices;
  19. namespace mojoPortal.Business
  20. {
  21. /// <summary>
  22. ///
  23. /// </summary>
  24. public sealed class LdapHelper
  25. {
  26. private LdapHelper()
  27. {
  28. }
  29. private static readonly ILog log = LogManager.GetLogger(typeof(LdapHelper));
  30. #region Static Methods
  31. private static LdapConnection GetConnection(LdapSettings ldapSettings)
  32. {
  33. LdapConnection conn = new LdapConnection();
  34. bool useSsl = false;
  35. if (ConfigurationManager.AppSettings["UseSslForLdap"] != null)
  36. {
  37. useSsl = Convert.ToBoolean(ConfigurationManager.AppSettings["UseSslForLdap"]);
  38. }
  39. if (useSsl)
  40. {
  41. // make this support ssl/tls
  42. //http://stackoverflow.com/questions/386982/novell-ldap-c-novell-directory-ldap-has-anybody-made-it-work
  43. conn.SecureSocketLayer = true;
  44. conn.UserDefinedServerCertValidationDelegate += new CertificateValidationCallback(LdapSSLHandler);
  45. }
  46. conn.Connect(ldapSettings.Server, ldapSettings.Port);
  47. return conn;
  48. }
  49. public static bool LdapSSLHandler(System.Security.Cryptography.X509Certificates.X509Certificate certificate, int[] certificateErrors)
  50. {
  51. #if !MONO
  52. X509Store store = null;
  53. X509Stores stores = X509StoreManager.LocalMachine;
  54. store = stores.TrustedRoot;
  55. X509Certificate x509 = null;
  56. byte[] data = certificate.GetRawCertData();
  57. if (data != null) { x509 = new X509Certificate(data); }
  58. if (x509 != null)
  59. {
  60. //coll.Add(x509);
  61. if (!store.Certificates.Contains(x509))
  62. {
  63. store.Import(x509);
  64. }
  65. }
  66. #endif
  67. return true;
  68. }
  69. private static LdapEntry GetOneUserEntry(
  70. LdapConnection conn,
  71. LdapSettings ldapSettings,
  72. string search)
  73. {
  74. LdapSearchConstraints constraints = new LdapSearchConstraints();
  75. LdapSearchQueue queue = null;
  76. queue = conn.Search(
  77. ldapSettings.RootDN,
  78. LdapConnection.SCOPE_SUB,
  79. ldapSettings.UserDNKey + "=" + search,
  80. null,
  81. false,
  82. (LdapSearchQueue)null,
  83. (LdapSearchConstraints)null);
  84. LdapEntry entry = null;
  85. if (queue != null)
  86. {
  87. LdapMessage message = queue.getResponse();
  88. if (message != null)
  89. {
  90. if (message is LdapSearchResult)
  91. {
  92. entry = ((LdapSearchResult)message).Entry;
  93. }
  94. }
  95. }
  96. return entry;
  97. }
  98. public static LdapUser LdapLogin(LdapSettings ldapSettings, string uid, string password)
  99. {
  100. if (ldapSettings.UserDNKey == "uid") //OpenLDAP
  101. {
  102. return LdapStandardLogin(ldapSettings, uid, password);
  103. }
  104. else //Active Directory
  105. {
  106. return ActiveDirectoryLogin(ldapSettings, uid, password);
  107. }
  108. }
  109. private static LdapUser LdapStandardLogin(LdapSettings ldapSettings, string uid, string password)
  110. {
  111. bool success = false;
  112. LdapUser user = null;
  113. LdapConnection conn = null;
  114. try
  115. {
  116. conn = GetConnection(ldapSettings);
  117. }
  118. catch (System.Net.Sockets.SocketException ex)
  119. {
  120. if (log.IsErrorEnabled)
  121. {
  122. log.Error("couldn't connect to ldap server ", ex);
  123. }
  124. }
  125. if ((conn != null) && (conn.Connected))
  126. {
  127. LdapEntry entry = null;
  128. try
  129. {
  130. entry = GetOneUserEntry(conn, ldapSettings, uid);
  131. if (entry != null)
  132. {
  133. LdapConnection authConn = GetConnection(ldapSettings);
  134. authConn.Bind(entry.DN, password);
  135. authConn.Disconnect();
  136. success = true;
  137. }
  138. }
  139. catch (Novell.Directory.Ldap.LdapException ex)
  140. {
  141. if (log.IsErrorEnabled)
  142. {
  143. log.Error("login failure", ex);
  144. }
  145. success = false;
  146. }
  147. if (success)
  148. {
  149. if (entry != null)
  150. {
  151. user = new LdapUser(entry);
  152. }
  153. }
  154. conn.Disconnect();
  155. }
  156. return user;
  157. }
  158. private static LdapUser ActiveDirectoryLogin(LdapSettings ldapSettings, string uid, string password)
  159. {
  160. bool success = false;
  161. LdapUser user = null;
  162. DirectoryEntry adentry = null;
  163. //Note: Not necessary to check SSL. Default authentication type for .NET 2.0+ is "Secure"
  164. try
  165. {
  166. adentry = new DirectoryEntry("LDAP://" + ldapSettings.Server, ldapSettings.Domain + "\\" + uid, password);
  167. }
  168. catch (System.Runtime.InteropServices.COMException ex)
  169. {
  170. if (log.IsErrorEnabled)
  171. {
  172. log.Error("couldn't connect to ldap server ", ex);
  173. }
  174. }
  175. if (adentry != null)
  176. {
  177. //Bind to the native AdsObject to force authentication.
  178. try
  179. {
  180. object testobj = adentry.NativeObject;
  181. success = true;
  182. }
  183. catch (System.Runtime.InteropServices.COMException ex)
  184. {
  185. if (log.IsErrorEnabled)
  186. {
  187. log.Error("login failure", ex);
  188. }
  189. success = false;
  190. }
  191. if (success && adentry != null)
  192. {
  193. user = new LdapUser(adentry, uid, ldapSettings);
  194. }
  195. }
  196. return user;
  197. }
  198. //public static LdapUser LdapLogin(LdapSettings ldapSettings, string uid, string password)
  199. //{
  200. // LdapConnection conn = null;
  201. // try
  202. // {
  203. // conn = GetConnection(ldapSettings);
  204. // }
  205. // catch (System.Net.Sockets.SocketException ex)
  206. // {
  207. // log.Error("couldn't connect to ldap server ", ex);
  208. // }
  209. // bool success = false;
  210. // LdapUser user = null;
  211. // if ((conn != null)&&(conn.Connected))
  212. // {
  213. // LdapEntry entry = null;
  214. // try
  215. // {
  216. // // open ldap uses uid
  217. // if(ldapSettings.UserDNKey == "uid")
  218. // {
  219. // entry = GetOneUserEntry(conn, ldapSettings, uid);
  220. // if(entry != null)
  221. // {
  222. // LdapConnection authConn = GetConnection(ldapSettings);
  223. // authConn.Bind(entry.DN, password);
  224. // authConn.Disconnect();
  225. // success = true;
  226. // }
  227. // }
  228. // else
  229. // {
  230. // // Active Directory uses CN
  231. // // might need this if other Ldap Servers besides Active Directory use CN
  232. // //conn.Bind(
  233. // // ldapSettings.UserDNKey + "=" + uid + "," + ldapSettings.RootDN, password);
  234. // // this works with Active Directory
  235. // conn.Bind(uid + "@" + ldapSettings.Domain, password);
  236. // success = conn.Bound;
  237. // entry = GetOneUserEntry(conn, ldapSettings, uid);
  238. // }
  239. // }
  240. // catch (Novell.Directory.Ldap.LdapException ex)
  241. // {
  242. // if (log.IsErrorEnabled)
  243. // {
  244. // log.Error("login failure", ex);
  245. // }
  246. // success = false;
  247. // }
  248. // if (success)
  249. // {
  250. // if (entry != null)
  251. // {
  252. // user = new LdapUser(entry);
  253. // }
  254. // else
  255. // {
  256. // user = new LdapUser(ldapSettings, uid);
  257. // }
  258. // }
  259. // conn.Disconnect();
  260. // }
  261. // return user;
  262. //}
  263. public static bool TestUser(LdapSettings ldapSettings, string uid, string password)
  264. {
  265. bool result = false;
  266. LdapUser testUser = LdapLogin(ldapSettings, uid, password);
  267. if (testUser != null)
  268. {
  269. result = true;
  270. }
  271. return result;
  272. }
  273. // public static LdapUser GetUser(LdapSettings ldapSettings, string uid)
  274. // {
  275. // LdapConnection conn = GetConnection(ldapSettings);
  276. // LdapUser user = null;
  277. //
  278. // if (conn.Connected)
  279. // {
  280. //
  281. // SiteSettings siteSettings = (SiteSettings)HttpContext.Current.Items["SiteSettings"];
  282. // SiteUser siteUser = new SiteUser(siteSettings, HttpContext.Current.User.Identity.Name);
  283. //
  284. // conn.Bind(ldapSettings.UserDNKey + "=" +siteUser.UserID+ "," + ldapSettings.RootDN, siteUser.Password);
  285. //
  286. // if (conn.Bound)
  287. // {
  288. // LdapEntry entry = GetOneUserEntry(conn, ldapSettings, uid);
  289. // user = new LdapUser(entry);
  290. // }
  291. //
  292. // conn.Disconnect();
  293. // }
  294. // return user;
  295. // }
  296. // public static bool UpdateUser(LdapDetails LdapSettings, LdapUser User)
  297. // {
  298. // bool success = false;
  299. //
  300. // LdapConnection conn = GetConnection(LdapSettings, true);
  301. //
  302. // try
  303. // {
  304. // conn.Modify(User.DN, User.Modifications);
  305. // success = true;
  306. // }
  307. // catch
  308. // {
  309. // success = false;
  310. // }
  311. //
  312. // return success;
  313. // }
  314. /* Left over LDAP Code
  315. private static LdapEntry GetOneGroupEntry(LdapConnection conn, LdapDetails ld, string GidNumber)
  316. {
  317. LdapSearchQueue queue = conn.Search(ld.adminemail,
  318. LdapConnection.SCOPE_ONE,
  319. "gidNumber="+GidNumber, null, false, (LdapSearchQueue)null, (LdapSearchConstraints)null);
  320. LdapMessage message = queue.getResponse();
  321. LdapEntry entry = null;
  322. if(message != null && message is LdapSearchResult)
  323. entry = ((LdapSearchResult)message).Entry;
  324. return entry;
  325. }
  326. public static string[] GetGroups(LdapDetails ld, string email)
  327. {
  328. ArrayList groups = new ArrayList();
  329. if(classConn == null || classConn.Connected)
  330. classConn = GetConnection(ld, true);
  331. LdapEntry entry = GetOneUserEntry(classConn, ld, email);
  332. string entryUID = ((LdapAttribute)entry.getAttribute("uid")).StringValue;
  333. //primary group
  334. string gidNumber = ((LdapAttribute)entry.getAttribute("gidNumber")).StringValue;
  335. LdapAttribute gidName = ((LdapEntry)GetOneGroupEntry(classConn, ld, gidNumber)).getAttribute("cn");
  336. groups.Add(gidName.StringValue);
  337. LdapSearchQueue queue = classConn.Search(ld.adminemail,
  338. LdapConnection.SCOPE_ONE,
  339. "memberUid="+entryUID,
  340. null,
  341. false,
  342. (LdapSearchQueue)null, (LdapSearchConstraints)null);
  343. LdapMessage message;
  344. LdapAttribute attr;
  345. while((message = queue.getResponse()) != null && message is LdapSearchResult)
  346. {
  347. entry = ((LdapSearchResult)message).Entry;
  348. attr = entry.getAttribute("uid");
  349. groups.Add(attr.StringValue);
  350. }
  351. classConn.Disconnect();
  352. string[] ret = new string[groups.Count];
  353. ret = (string[])groups.ToArray(typeof(string));
  354. return ret;
  355. }
  356. public static int UserCount(LdapDetails ld)
  357. {
  358. if(classConn == null || !classConn.Connected)
  359. classConn = GetConnection(ld, true);
  360. LdapSearchQueue queue = classConn.Search(ld.UserBaseDN, LdapConnection.SCOPE_ONE, "uid=*", null, false, (LdapSearchQueue)null, (LdapSearchConstraints)null);
  361. int temp = 0;
  362. LdapMessage message = queue.getResponse();
  363. while(message != null && message is LdapSearchResult)
  364. {
  365. temp++;
  366. message = queue.getResponse();
  367. }
  368. classConn.Disconnect();
  369. return temp;
  370. }
  371. public static DataSet GetUserListPage(LdapDetails ld, int PageNumber, int PageSize, string NameBeginsWith)
  372. {
  373. DataTable dt = new DataTable();
  374. dt.Columns.Add("UserID", typeof(int));
  375. dt.Columns.Add("Name", typeof(string));
  376. dt.Columns.Add("WebSiteUrl", typeof(string));
  377. dt.Columns.Add("Email", typeof(string));
  378. dt.Columns.Add("TotalPosts", typeof(int));
  379. if(classConn == null || !classConn.Connected)
  380. classConn = GetConnection(ld, true);
  381. NameBeginsWith = NameBeginsWith.ToLower();
  382. LdapSearchQueue queue = classConn.Search(ld.UserBaseDN, LdapConnection.SCOPE_ONE, "uid="+NameBeginsWith+"*", null, false, (LdapSearchQueue)null, (LdapSearchConstraints)null);
  383. int counted = 0;
  384. int messid = (PageNumber-1)*PageSize;
  385. LdapMessage message = queue.getResponse();
  386. DataRow dr;
  387. LdapEntry entry;
  388. LdapAttributeSet las;
  389. while(message != null && message is LdapSearchResult && counted < PageSize)
  390. {
  391. dr = dt.NewRow();
  392. entry = ((LdapSearchResult)message).Entry;
  393. las = entry.getAttributeSet();
  394. foreach(LdapAttribute a in las)
  395. {
  396. switch(a.Name)
  397. {
  398. case "cn":
  399. dr["Name"] = a.StringValue;
  400. break;
  401. case "uidNumber":
  402. dr["UserID"] = Convert.ToInt32(a.StringValue);
  403. break;
  404. case "mail":
  405. dr["Email"] = a.StringValue;
  406. break;
  407. case "url":
  408. dr["WebSiteUrl"] = a.StringValue;
  409. break;
  410. }
  411. }
  412. dt.Rows.Add(dr);
  413. messid++;
  414. counted++;
  415. message = queue.getResponse();
  416. }
  417. classConn.Disconnect();
  418. DataSet ds = new DataSet();
  419. ds.Tables.Add(dt);
  420. return ds;
  421. }
  422. */
  423. #endregion
  424. }
  425. }