Sunday, October 20, 2013

LINQ to LDAP Examples

I've been working on a "Getting Started" guide and an official examples project. A friend of mine created LINQ to LDAP Demonstrations to help me out since I was slacking and not keeping the samples project up to date. The new examples point to two live OpenLDAP servers (thanks to Stuart Lewis and the University of Texas) so you can actually play around with the framework.

Some of the examples highlight the differences between plain old DirectoryServices and LINQ to LDAP. Not everything works correctly using DirectoryServices (i.e. paging) so I've made the queries pretty basic so everything works across the board. If you know of a publicly accessible AD/AD-LDS server then let me know. You can find the examples here.

Monday, October 8, 2012

LINQ to LDAP: Event Listeners

I'm adding support for listening to Add, Update, and Delete operations in the latest version of LINQ to LDAP. This will allow you to perform validation or logging operations before anything is executed. So let's try this out:



There are 3 interfaces that you can implement to subscribe to events: IPreAddEventListener, IPreDeleteEventListener, IPreUpdateEventListener. Each interface has a Notify method that will give you access to the entry being modified (the mapped object, the DirectoryAttributes, or the Distinguished Name in the case of Delete), the LdapConnection used for the modification, and the DirectoryRequest that will be sent. The DirectoryRequest won't have any of the attribute values added since you may want to do validation beforehand. You can also add / modify anything you want about the request.

Using your event listener is pretty straightforward:



When using the LdapConfiguration you can call RegisterListener and it will be used across all DirectoryContexts. When using the LdapConnection extension methods you can pass it in as a parameter. And that's about it.

Sunday, October 7, 2012

LINQ to LDAP: Attribute Scoped Queries

Active Directory has supported this feature since Windows Server 2003, however I only learned about it recently from Simon Garratt. An attribute scoped query allows you to search within any multivalued attribute of an entry. This becomes really useful when you want to search for users within a group without performing multiple queries.

Say you want to find all users in the sales department for a group:



So what's going on here? I'm looking for User objects stored in "CN=Group,DC=server,DC=com" and I'm using a base search scope since I'm looking within a specific distinguished name.

On the second line I call ScopeToAttribute and I give it the name of the attribute on the group (member in this case). On a side note, ScopeToAtribute is just some syntactic sugar for calling WithControls and passing in a AsqRequestControl.

On the third line I'm just creating a standard filter. Since I'm querying for users my filter will be in that context. I can search on any User property and create any projection from a User.

I think this is pretty cool since it goes for any multivalued attribute that links to other directory entries (members, groups, employees, etc.).

Sunday, July 8, 2012

LINQ to LDAP: The Other Lync

Lync is Microsoft's unified communication platform. It ships with a pretty awesome SDK that makes adding presence information to your WPF and Silverlght apps pretty easy. It's also possible to add presence information to your ASP.Net apps, but it's a little trickier. The first thing you'll need for WPF or Silverlight is the SDK. The installed assemblies should be located in Program Files (or the x86 variant if you're running 64bit) under Microsoft Lync\SDK\Assemblies.

You'll need Microsoft.Lync.Controls.Framework.dll, Microsoft.Lync.Controls.dll, Microsoft.Lync.Model.dll, and Microsoft.Lync.Utilities.dll. Reference those assemblies and you're ready to drop in a control:



The PresenceIndicator control gives you the familiar jelly bean and the image of the person. The Source property should be bound to the user's SIP Uri. What the heck is a SIP Uri? The short version is that it is the address for initiating a communication session with a user via Session Initiation Protocol. You can read the long version here and here.

You may be asking yourself what any of this has to do with LINQ to LDAP. Odds are if you are tracking anything about your users in your applications it's either the sAMAccountName or the Guid. The SIP Uri for those users, however, is stored in the msRTCSIP-PrimaryUserAddress attribute. You can perform a simple lookup to get this attribute. Query by example will not work in this case since the property name is invalid, but mapping or dynamic querying will work.



ASP.Net isn't quite as straightforward. Here's a great post about piggybacking on the NameCtrl in SharePoint 2010. Make sure you do not prefix the uri with "sip:" in the ASP.Net example or it won't work.

Friday, June 22, 2012

LINQ to LDAP: Closer to Home

During my experience with passwords I was working directly with an LdapConnection. After a while I wondered how easy it would be to add extension methods directly to the LdapConnection. It was actually pretty easy so all of the methods that don't rely on object mappings are now available from an LdapConnection object now.

Thursday, June 21, 2012

LINQ to LDAP: How do passwords work?

A couple hours of trial and error I have finally figured out setting passwords in Active Directory and Lightweight Directory Services. As a result of this I ported all of the dynamic functionality to some extension methods for LdapConnection.

Modifying passwords has been in the back of my head ever since the question was asked here. If I had looked closer at the answer on StackOverflow I would have seen that the solution was for Sun-One. If there's one thing I've learned working on LINQ to LDAP it's that every server has been implemented a little differently.

So let's get down to it. The first thing I learned is userPassword in AD LDS is not the "real" password attribute. That would be unicodePwd. I then received a very helpful "An operation error occurred." A few searches later and I found out that means you'll have to use port 636 instead of 389. Turns out Microsoft does not allow changing the password over a non SSL connection. However, you don't have to explicitly set SSL to true if you're post Windows 2000 (I hope you are). Okie dokie let's fire this up.

"The LDAP server is unavailable."

You'll get this error if SSL is not on for your server. This lead me to generating a self signed certificate and installing it for my local instance. You can read about the how and why here. Alright, now my server is responding to requests on 636, but I'm getting "A value in the request is invalid." That's when I found this post explaining how to do this the right way. I wish I had found that first. So here's the resulting code:



For those using AD LDS and you don't have SSL on, let me save you some trouble. I found this post later allowing you to enable modifying the password over port 389. Well I hope this was helpful.

update
I should probably add that you should not enable setting passwords over an unencrypted connection. I am working in a test environment so it's no big deal for me.

Monday, June 11, 2012

LINQ to LDAP: Documentation

Just a minor update. 3.0 is coming. I'm currently reviewing and updating the documentation over at CodePlex. I realized that I haven't touched it since sometime around 1.5 / 2.0 so it's in dire need of a refresh. There are a few things from 3.0 in there so don't download 2.5 and scream "WTF, this is all wrong!" :).