Mono in Practice

Gordon Mathis

Developer Solutions

Senior Software Engineer

gmathis@novell.com

Objectives

Get introduced to the .NET Framework interface for directories

Kick-start developing Directory applications on Linux using Mono

Build C# applications that leverage existing LDAP Infrastructure or Identity Store

Aimed at Developers and Architects

Agenda

Introduction

.NET C# LDAP Library

Setting up your Development Environment

Examples

System.DirectoryServices Namespace

DirectoryEntry class

Life Cycle Management of Directory Objects

DirectorySearch class

What is Mono?

Mono

is an open source implementation of the

Microsoft .NET Framework.

Mono includes:

a compiler for the C# language, an ECMA-compatible runtime engine for the Common Language Infrastructure (also referred as the CLR) and class libraries: both Microsoft .NET compatible as well as many more.

What is LDAP?

Lightweight Directory Access Protocol

IETF standards-based, described in RFC 2251-2256 and RFC 2829-2830

Internet request/response protocol for accessing data stored in a network directory

X.500 entry based Model.

C# LDAP API

Developing .NET LDAP Application

User Data

Application Data

LDAP

Interaction

LDAP Application

.NET Platform

Application A

Application B

LDAP

Gateway

Backend

Interaction

Identity

Store

.NET C# LDAP Library

.NET C# LDAP Library

Based on the LDAP API defined by IETF Java LDAP draft ( Currently version 18) avaliable at www.ietf.org

Released under the Novell.Directory.Ldap Namespace.

.NET C# LDAP Library

Novell.Directory.Ldap.Asn1

Provides ASN.1 encoding and decoding classes using Basic Encoding Rules (BER).

Used for developing new LDAP controls or extensions

Flexible enough to allow an application to provide its own encoding format.

Novell.Directory.Ldap.Asn1

.NET C# LDAP Library

Novell.Directory.Ldap.Utilclass

Provides utility classes for use by LDAP applications

Includes DN and RDN Classes supporting DN and RDN encapsulation.

Novell.Directory.Ldap.Asn1

Novell.Directory.Ldap.Utilclass

.NET C# LDAP Library

Novell.Directory.Ldap.Rfc2251

Provides classes that represent protocol elements as defined by the IETF LDAP RFC 2251.

Novell.Directory.Ldap.Asn1

Novell.Directory.Ldap.Utilclass

Novell.Directory.Ldap.Rfc2251

.NET C# LDAP Library

Novell.Directory.Ldap.Controls

Provides classes for using IETF and Novell defined extensions to change the behavior of search operations

Sort, Persistant Search,
Virtual List Controls

Novell.Directory.Ldap.Asn1

Novell.Directory.Ldap.Utilclass

Novell.Directory.Ldap.Rfc2251

Novell.Directory.Ldap.Controls

.NET C# LDAP Library

Novell.Directory.Ldap.Extensions

Provides classes for using the Novell LDAP extensions

To manage replicas, naming contexts, and the synchronization of replicas and schema

Requires the LDAP Server to run on eDirectory.

Novell.Directory.Ldap.Asn1

Novell.Directory.Ldap.Utilclass

Novell.Directory.Ldap.Rfc2251

Novell.Directory.Ldap.Controls

Novell.Directory.Ldap.Extensions

.NET C# LDAP Library

Novell.Directory.Ldap

Provides classes for the core C# LDAP library, which is most frequently used by applications.

Provides Classes for Managing entry and Schema and Schema Definition

Novell.Directory.Ldap.Asn1

Novell.Directory.Ldap.Utilclass

Novell.Directory.Ldap.Rfc2251

Novell.Directory.Ldap.Controls

Novell.Directory.Ldap.Extensions

Novell.Directory.Ldap

Setting up your Dev. Environment

System Requirement

Linux

Mono (compiler, runtime and class libraries) .

Windows

Microsoft .NET SDK OR Mono (compiler, runtime and class libraries)

You can download mono from:

http://www.go-mono.com/download.html.

Setting up your Dev. Environment
(Cont.)

Linux

Copy Novell.Directory.Ldap.dll to an appropriate location in your project.

Set directory containing Novell.Directory.Ldap.dll in your MONO_PATH variable as follows:

In your project Makefile set reference to Novell.Directory.Ldap.dll using /r:/home/sunilk/project/lib/Novell.Directory.Ldap.dll

Add the following line to your code

Compiling from command line

Novell.Directory.Ldap.dll library location

/usr/lib/mono/1.0

Compile

mcs /r:/usr/lib/mono/1.0/Novell.Directory.Ldap.dll AddEntry.cs

Execute

mono AddEntry.exe 127.0.0.1 389 “cn=admin,o=novell” novell “o=novell”

Installing Mono Develop

MonoDevelop requires the following packages to be installed in this order (http://mono-project.com/Downloads)

mono-core-1.0.6-1.ximian.9.1.i586.rpm

mono-devel-1.0.6-1.ximian.9.1.i586.rpm

mono-locale-extras-1.0.6-1.ximian.9.1.i586.rpm

gtk-sharp-1.0.6-0.ximian.9.1.i586.rpm

gecko-sharp-0.6-1.ximian.9.1.i586.rpm

gtksourceview-sharp-0.5-1.ximian.9.1.i586.rpm

mono-data-1.0.6-1.ximian.9.1.i586.rpm

mono-web-1.0.6-1.ximian.9.1.i586.rpm

monodoc-1.0.5-1.ximian.9.1.i586.rpm

monodevelop-0.5.1-1.ximian.9.1.i586.rpm

xsp-1.0.6-1.ximian.9.1.i586.rpm

Setting up your Dev. Environment (Cont.)

Windows

Copy Novell.Directory.Ldap.dll to an appropriate location in your project

Start Visual Studio .NET.

Select File->New->Project.

In the Project Type column, select the project type to create C#

In the Template column, select a project template (like Console Application, Windows Application).

Name your project.

Click OK to create your new project.

Select Project->Add reference->Browse

In Browse select Novell.Directory.Ldap.dll from the location you copied in step 1.

LdapConnection Class

Represents socket connection to LDAP Server

Supports cloning which enables Multiple threads to share a connection

Cloned connections have all settings of original

Clone shares connection with original

Subsequent changes to clone do not affect original

Closing clone connection does not affect original

Rebinding affects all clones

Application can have more than one LdapConnection class

Connected to same or different directory servers

Construction does not call connect

Bind/unbind Example

LdapConnection conn = new LdapConnection();

conn.Connect (ldapHost,ldapPort);

conn.Bind (ldapVersion,dn,password);

Console.WriteLine( (conn.Bound) ? “Connection is

Authenticated”:”Connection is Anonymous”);

If(conn.Connected)

conn.Disconnect();

Calling the constructor

does not actually establish

the LDAP connection

When more than one host

name is Specified each host

is contacted in turn until a

connection is established

Uses specified dn and

password to Authenticate

against the connected

LDAPServer

Indicated whether the

Objectis authenticated

To the connected ldap

Server or not

Indicated whether the

connection represented

by this object is open

or not.

Abandons Any outstanding

Request. Issues LDAP

Unbind request and closes

The socket

LdapException Class

Includes an error message and an LDAP error code

Can result from physical problems

Network errors

Can result from problems with LDAP operations

LDAP add operation fails because of a duplicate entry

Can originate from Server or Client

Example client exceptions

Connection lost

Parameter error

Invalid filter

LdapException

LdapException.ResultCode Property

Returns specific result code

Can be compared against standard LDAP result codes

See RFC2251

LdapException.Cause Property

Provides additional error information

Such as IOException

LdapConnection.Search

LdapSearchResults Search(	String searchBase, int scope,

String filter, String[] attrs,

bool typesOnly)

Synchronously performs the search specified by the parameters

LdapSearchQueue Search(	String searchBase, int scope,

String filter, String[] attrs,

bool typesOnly,

LdapSearchQueue queue)

Asynchronously performs the search specified by the parameters

Search Example

LdapSearchResults searchResults=

conn.Search (	searchBase,

searchScope,

searchFilter,

null,

false);

// Parsing Search Results

while ( searchResults.hasMore() ) {

LdapEntry nextEntry = null;

try{

nextEntry = searchResults.next();

}	catch( LdapException e)	{

Cont.

Specifies the depth of the Search operation. Can be any of the three values base level, one level or subtree level

DN of the entry in the tree

Where you want the search

To begin

Represents a single entry in

a directory.

This while loop goes through all the entries.

If true return only attribute name. If false returns both attribute name and value.

Indicates which attributes to return. A null values means

return all attributes

Defines the search

comparison

A collection of LdapAttributes

which represents a name

value pair of one attribute

of a directory entry.

Search Example Cont.

Console.WriteLine(e.toString());

// Exception is thrown, go for next entry

continue;

}

Console.WriteLine("\n" + nextEntry.getDN());

LdapAttributeSet attributeSet = nextEntry.getAttributeSet();

System.Collections.IEnumerator allAttributes =	attributeSet.GetEnumerator();

while(allAttributes.MoveNext())	{

Cont.

Returns a simple iterator

over the attributes stored

In the Set. Attributes returned

May not eb in any particular

Order.

Print the entry DN.

This while loop goes through all the attributes of the entry

Returns a simple iterator

over the attributes stored In the Set.

Attributes returned May not be in any

particular order.

Search Example Cont.

LdapAttribute attribute =

(LdapAttribute)allAttributes.Current();

String attrName = attribute.Name;

System.Collections.IEnumerator allValues =

attribute.StringValues;

while( allValues.MoveNext() ) {

String Value = (String) allValues.Current;

Console.WriteLine ( attrName + “:” + Value );

}

}

}

Returns the name of the attribute

Returns a simple iterator

over the string values of

an attributes.

This while loop goes through all the attributes values

Constraints

May affect client or server

LdapSearchConstraints

LdapConstraints

Options that affect any operation
on current LdapConnection Object

Options that only affect
the search operation

LdapConstraints

Set of options to control an LDAP operation

LdapConstraints is always associated with an
LdapConnection object (clone)

Set using LdapConnection.Constraints

Or overridden by passing an LdapConstraints object
to an operation

public LdapConstraints(

int msLimit,	/* Max milliseconds to wait for results

bool doReferrals,	/* true - follow referrals automatically

/* false – throw LdapReferralException

/* if server sends back a referral

LdapReferralHandler binder,	/* custom authentication

/* processor when following referrals

int hop_limit	/* Max number of referrals to follow

)

LdapSearchConstraints

public LdapSearchResults search(

String searchBase,

int searchScope,

String searchFilter,

String[] attrs,

bool typesOnly

LdapSearchConstraints constraints)

Pass LdapSearchConstraints to Search method

LdapSearchConstraints

public LdapSearchConstraints(

int msLimit,

bool doReferrals,

LdapReferralHandler binder,

int hop_limit

int serverTimeLimit,

int dereference,

int maxResults,

int batchSize

)

/* Max time to wait for results

/* If referrals followed automatically */

/* Called when the LdapConnection needs to
/* authenticate, typically on following a
/* referral

/* Maximum number of referrals to follow

/* Max time server should spend

/* returning results

/* When aliases should be dereferenced

/* Max number search results to return */

/* Number results to return in a batch

/* 0 - block until all results are in

/* 1 - return results one at a time

/* >1 - return in batch of int */

LDAPSearchConstraints.batchSize

batchSize = 1

Default

Application handles each entry as each is returned

Application does not block waiting for all results to be returned, memory is not required to maintain entire list

If the application finishes processing before the next entry is returned, LDAPSearchResults.next will block

batchSize = O

Application blocks until all LDAPEntries are returned

Can cause delays in application responsiveness

Can cause memory problems as the entire list is generated locally before entries are handled

batchSize = int

Application waits until specified number of entries
is returned, then processes them

Add Example

LdapAttributeSet attributeSet = new LdapAttributeSet();

LdapAttribute attr = new LdapAttribute( "cn",new string[]{"James Smith", "Jim Smith"});

attributeSet.Add(attr);

attr = new LdapAttribute( "objectclass", "inetOrgPerson")

attributeSet.Add(attr);

attr=new LdapAttribute("sn", "Smith");

attributeSet.Add(attr);

string dn = "cn=KSmith,o=org”;

LdapEntry newEntry = new LdapEntry( dn, attributeSet );

conn.Add( newEntry );

Add all the attributes of

the entry to an attribute

Set

Creates the attribute of an entry

Speciy the DN of the entry

Uses DN and attributeSet to Create an LdapEntry Object

Adds the entry to the directory

System.DirectoryServices
Namespace

System.DirectoryServices Namespace

Provides Access to any LDAP Server

Built on top of .NET C# LDAP Library.

Part of .NET framework

Two major classes does the majority of task

DirectoryEntry

DirectorySearcher

Overview of System.DirectoryServices

System.DirectoryServices

Managed Code

Novell.Directory.Ldap

LDAP

eDirectory

Active Directory

Other LDAP Directory

System.DirectoryServices

Managed Code

Novell.Directory.Ldap

LDAP

eDirectory

Active Directory

Other LDAP Directory

System.DirectoryServices

Managed Code

Novell.Directory.Ldap

LDAP

eDirectory

Active Directory

Other LDAP Directory

Mono Vs. NET Implementation

System.DirectoryServices

Managed Code

LDAP

eDirectory

Active Directory

Other LDAP Directory

System.DirectoryServices

Managed Code

ADSI

LDAP

WinNT

NDS

Mono

MS .NET

Novell.Directory.Ldap

eDirectory

Active Directory

Other LDAP Directory

DirectoryEntry

Each object in the directory is represented as DirectoryEntry

What can you do with an object?

Modify its properties

Rename, Move

Enumerate its children

Create children

Delete its children

Get its identity

Get its parent

DirectoryEntry

DirectoryEntry

DirectoryEntry Properties

Gets or sets the username to use when authenticating

Username

Gets DirectoryEntry class of the object's objectclass

SchemaEntry

Gets the objectclass of the object

SchemaClassName

Gets a PropertyCollection class containing the attributes on the object.

Properties

Gets or sets the Path for the object

Path

Gets or sets the password to use when authenticating

Password

Gets the object's parent in directory.

Parent

Gets the relative distinguished name of the object.

Name

Gets a collection of child entries of this object

Children

Gets or sets the type of authentication to use when accessing the directory

AuthenticationType

Description

Property Name

DirectoryEntry Methods

String representation of the object

ToString

Rename the relative distinguished name of the object

Rename

Refresh the property cache for the object

RefreshCache

Move an object to a different location

MoveTo

Gets or sets the Path for the object

Exists

Determines if two objects are the same

Equals

Delete the object and any children

DeleteTree

Creates a copy of the object

CopyTo

Saves any changes to the object in Directory

CommitChanges

Closes the DirectoryEntry and releases any system resources associated with the component

Close

Description

Method Name

DirectoryEntry Example

using System.DirectoryServices;

DirectoryEntry entry = new DirectoryEntry( path);

Console.WriteLine( entry.Path );

Console.WriteLine( entry.Name );

DirectoryEntry parent = entry.Parent;

Create a directory entry object in memory, does not create object in the directory.

Directory Path, a string that
includes distinguished name.

Path, Name,

Parent are
always available

Create a directory entry object in memory, does not create object in the directory.

Binding To An Object

Client can connect to any LDAP server

E.g., “LDAP://server01”, LDAP://server02”

Client can bind to any object in the directory

Specify object’s distinguished name

Subject to access check

Path format

LDAP://[serverName/] [DistinguishedName]

Client may pass alternate credentials, specify authentication method, encryption mechanism, etc.

Binding Examples

DirectoryEntry();

DirectoryEntry(“LDAP://server01/CN=John, OU=PM,
O=Org”);

DirectoryEntry(“LDAP://server01/OU=PM, O=Org”,	userName, password);

DirectoryEntry(“LDAP://O=Org”, null, null,	AuthenticationTypes.ServerBind);

Navigation

Navigating to Child Object

Navigating to Parent Object

Browsing Child object Properties

Childrens

Entry

Parent

Example

for each(DirectoryEntry child in entry.Children) {
Console.WriteLine(child.Name);

}

DirectoryEntry parent = entry.Parent;

DirectoryEntry child = entry.Children.Find(“OU=PM”);

string name = entry.Properties["sn"].Value.ToString();

foreach(String s in ent.Properties[“cn"] ) Console.WriteLine(s);

Each DirectoryEntry

Has a collection object

,Named Children

To access a single valued

Property use the Value

property of the

PropertyValueCollection

Properties contains a

Collection of the

attributes of the entry

PropertyValueCollection

object, which contains a

collection of all the values

For the specified property

To get its Parent use Parent

To access a multi valued

Property use foreach

statement to retrieve

a Properties collection

To get to a specific

Child use . Find()

Life Cycle Management of Directory Objects

Create/Add Entry

Modify Entry

Delete Entry

Rename Entry

Move Entry

Create/Add Entry

DirectoryEntry de =

new DirectoryEntry("LDAP://ou=PM,O=Org“);

DirectoryEntry newEntry =

de.Children.Add("CN=Smith", “inetOrgPerson");

newEntry.CommitChanges();

Bind to the Container that

the object is to be added to

Use the Children property of

Container Object class to

add new directory object to

the container

Call CommitChanges to

save the object from the

cache to the directory

Modify Entry

DirectoryEntry de =

new DirectoryEntry("LDAP://cn=Ksmith,ou=PM,O=Org“);

de.Properties[“telephonenumber”].Add(“(91) 80 31815878”);

de.Properties[“sn”].Value=“Barr”;

de.CommitChanges();

Bind to the entry

Whose Property is

to be modified

Use Add() method of

PropertyValueCollection

to add a value to a

property

Use Value Property of

PropertyValueCollection

to set a new value to the

Single valued property

PropertyValueCollection

object, which contains a

collection of all the values

For the specified property

Call CommitChanges to

save the object from the

cache to the directory

Delete Entry

DirectoryEntry de =

new DirectoryEntry("LDAP://ou=PM,O=Org");

DirectoryEntry entryToRemove =

new DirectoryEntry(“LDAP://cn=Ksmith,OU=PM,O=Org");

de.Children.Remove(entryToRemove);

de.DeleteTree();

Bind to the Container whose

Child entry has to be deleted

Set entryToRemove to the child entry you want to remove

Use the Children property of

Container Object class to

remove child entry from

the container

Call DeleteTree()

method to Delete entry and all of its

children

Rename and Move Entry

DirectoryEntry de =

new DirectoryEntry("LDAP://cn=Ksmith,ou=PM,O=Org");

de.Rename(“cn=New User Name”);

DirectoryEntry newParent=

new DirectoryEntry(“LDAP://OU=Sales,O=org”)

de.MoveTo(newParent);

De.MoveTo(newParent,”cn=New User Name”);

Bind to the Parent entry

where the entry has to

be Moved

Bind to the entry which

has To be renamed

Call Rename() method to rename the

entry

Call MoveTo() method to Move the entry to new

Conatiner

MoveTo() method with new RDN, Moves and renames the entry Simultaneously

DirectorySearcher

Search and perform queries against a Directory hierarchy using the Lightweight Directory Access Protocol (LDAP).

Works like many other LDAP-based search APIs.

1

Base DN of Search

ou=Marketing,o=org

Search Filter (ObjectClass=*)

Search Scope

Base,OneLevel,SubTree

Attributes Returned

Sn,cn,title….

DirectorySearcher Properties

Gets or sets the maximum number of objects that can be returned by a search

SizeLimit

Gets or sets the time the server will wait for a search to complete

ServerTimeLimit

Gets or sets the time the server will wait for an individual page to return from a search.

ServerPageTimeLimit

Gets or sets the scope of the search

SearchScope

Gets or sets the base from which the search should start

SearchRoot

Gets or sets whether referrals are chased.

ReferralChasing

Gets or sets the flag that indicates that only attribute names are to be returned from a search.

PropertyNamesOnly

Gets or sets the attributes to return from a search

PropertiesToLoad

Gets or sets the page size for paged searching.

PageSize

Gets or sets the search filter string.

Filter

Gets or sets the time period the client is willing to wait for the server to answer the search

ClientTimeout

Gets or sets the flag that determines if results are cached on the client side.

CacheResults

Description

Property Name

DirectorySearcher Methods

Provides Two methods to perform the Search:

FindOne returns a single item.

FindAll returns a collection of items

DirectorySearcher Example

DirectoryEntry root =

new DirectoryEntry( “LDAP://OU=PM,O=Org”);

DirectorySearcher mySearcher=

new DirectorySearcher(root);

mySearcher.SearchScope = SearchScope.Subtree;

mySearcher.Filter = “(&(objectclass=*)(cn=sun*));

SearchResultCollection result = mySearcher.FindAll();

// Handle Result

Bind to the root entry (Base

DN). For optimal performance

Select the root enrty that

Provide smallest result set

Create a DirectorySearcher

Object.

Return a collection

Of Items matching

the Search Criteria

Search all object

In the subtree starting from root

Sets the Search

comaprison

Developer References

Using .NET C# Library

http://www.novell.com/coolsolutions/cooldev/features/a_net_cplus_ldap_library_cdev.html

Mono

http://www.go-mono.com

.Net C# LDAP Library project

http://forge.novell.com/modules/xfmod/project/?ldapcsharp

System.DirectoryServices

http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemDirectoryServices.asp

Novell Developer LDAP SDKs, documentation, and samples

http://developer.novell/ndk

Novell eDirectory Evaluation Version and Redistribution kit

http://www.novell.com/products/edirectory/

General Disclaimer

This document is not to be construed as a promise by any participating company to develop, deliver, or market a product. Novell, Inc., makes no representations or warranties with respect to the contents of this document, and specifically disclaims any express or implied warranties of merchantability or fitness for any particular purpose. Further, Novell, Inc., reserves the right to revise this document and to make changes to its content, at any time, without obligation to notify any person or entity of such revisions or changes. All Novell marks referenced in this presentation are trademarks or registered trademarks of Novell, Inc. in the United States and other countries. All third-party trademarks are the property of their respective owners.

No part of this work may be practiced, performed, copied, distributed, revised, modified, translated, abridged, condensed, expanded, collected, or adapted without the prior written consent of Novell, Inc. Any use or exploitation of this work without authorization could subject the perpetrator to criminal and civil liability.

This means that no work is lost with either the Novell Nsure UDDI corporate or testing solution.

Enterprises that build their UDDI solutions with Novell Nsure UDDI Server, are not only leveraging the deep experience Novell Identity Management foundation brings to the standard, they are securing their own future by building on an open standard implementation that will grow and scale with their corporate needs.

2005-02-02T11:14:34