~ifolder-dev/simias/trunk-packaging

« back to all changes in this revision

Viewing changes to src/server/Simias.OpenLdapProvider/.svn/text-base/OpenLdapSync.cs.svn-base

  • Committer: Jorge O. Castro
  • Date: 2007-12-03 06:56:46 UTC
  • Revision ID: jorge@ubuntu.com-20071203065646-mupcnjcwgm5mnhyt
* Remove a bunch of .svn directories we no longer need.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/****************************************************************************
2
 
 |
3
 
 | Copyright (c) 2007 Novell, Inc.
4
 
 | All Rights Reserved.
5
 
 |
6
 
 | This program is free software; you can redistribute it and/or
7
 
 | modify it under the terms of version 2 of the GNU General Public License as
8
 
 | published by the Free Software Foundation.
9
 
 |
10
 
 | This program is distributed in the hope that it will be useful,
11
 
 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 | GNU General Public License for more details.
14
 
 |
15
 
 | You should have received a copy of the GNU General Public License
16
 
 | along with this program; if not, contact Novell, Inc.
17
 
 |
18
 
 | To contact Novell about this file by physical or electronic mail,
19
 
 | you may find current contact information at www.novell.com
20
 
 |
21
 
 |  Author: Bruce Getter <bgetter@novell.com>
22
 
 |***************************************************************************/
23
 
 
24
 
using System;
25
 
 
26
 
using Novell.Directory.Ldap;
27
 
using Novell.Directory.Ldap.Utilclass;
28
 
 
29
 
using Simias;
30
 
using Simias.LdapProvider;
31
 
using Simias.Storage;
32
 
 
33
 
namespace Simias.OpenLdapProvider
34
 
{
35
 
        /// <summary>
36
 
        /// Service class used to get an execution context
37
 
        /// so we can register ourselves with the external
38
 
        /// sync container
39
 
        /// </summary>
40
 
        class OpenSync : Simias.IIdentitySyncProvider
41
 
        {
42
 
                #region Class Members
43
 
                private readonly string name = "Open LDAP Synchronization";
44
 
                private readonly string description = "Open LDAP Synchronization provider to synchronize identities from Active Directory to a simias domain";
45
 
                private bool abort = false;
46
 
                
47
 
                private Simias.LdapProvider.Status syncStatus;
48
 
                private static LdapSettings ldapSettings;
49
 
                private Exception syncException;
50
 
 
51
 
                private Store store = null;
52
 
                private Domain domain = null;
53
 
                
54
 
                private LdapConnection conn = null;
55
 
                private Simias.IdentitySync.State state = null;
56
 
                
57
 
                /// <summary>
58
 
                /// Used to log messages.
59
 
                /// </summary>
60
 
                private static readonly ISimiasLog log = 
61
 
                        SimiasLogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
62
 
                #endregion
63
 
                
64
 
                #region Properties
65
 
                /// <summary>
66
 
                /// Gets the name of the provider.
67
 
                /// </summary>
68
 
                public string Name { get{ return name; } }
69
 
 
70
 
                /// <summary>
71
 
                /// Gets the description of the provider.
72
 
                /// </summary>
73
 
                public string Description { get{ return description; } }
74
 
                #endregion
75
 
                
76
 
                #region Private Methods
77
 
                
78
 
                private void ProcessSearchObjects( LdapConnection conn, LdapSettings settings )
79
 
                {
80
 
                        foreach ( string searchContext in settings.SearchContexts )
81
 
                        {
82
 
                                string[] searchAttributes = { "objectClass" };
83
 
 
84
 
                                log.Debug( "SearchObject: " + searchContext );
85
 
 
86
 
                                try
87
 
                                {
88
 
                                        LdapEntry ldapEntry = conn.Read( searchContext, searchAttributes );
89
 
                                        LdapAttribute attrObjectClass = ldapEntry.getAttribute( "objectClass" );
90
 
                                        String[] values = attrObjectClass.StringValueArray;
91
 
 
92
 
                                        if ( IsUser( values ) == true )
93
 
                                        {
94
 
                                                // Process SearchDN as 
95
 
                                                log.Debug( "Processing User Object..." );
96
 
                                                ProcessSearchUser( conn, searchContext );
97
 
                                        }
98
 
                                        else if ( IsGroup( values ) == true )
99
 
                                        {
100
 
                                                // Process SearchDN as 
101
 
                                                log.Debug( "Processing Group Object..." );
102
 
                                                ProcessSearchGroup( conn, searchContext );
103
 
                                        }
104
 
                                        else if ( IsContainer( values ) == true )
105
 
                                        {
106
 
                                                // Process SearchDN as Container
107
 
                                                log.Debug( "Processing Container Object..." );
108
 
                                                ProcessSearchContainer( conn, searchContext );
109
 
                                        }
110
 
                                        else
111
 
                                        {
112
 
                                                log.Debug( "Invalid objectClass: " + values[0] );
113
 
                                                log.Debug( attrObjectClass.ToString() );
114
 
                                        }
115
 
                                }
116
 
                                catch( SimiasShutdownException s )
117
 
                                {
118
 
                                        log.Error( s.Message );
119
 
                                        throw s;
120
 
                                }
121
 
                                catch ( LdapException e )
122
 
                                {
123
 
                                        log.Error( e.LdapErrorMessage );
124
 
                                        log.Error( e.StackTrace );
125
 
                                }
126
 
                                catch ( Exception e )
127
 
                                {
128
 
                                        log.Error( e.Message );
129
 
                                        log.Error( e.StackTrace );
130
 
                                }
131
 
                        }
132
 
                }
133
 
 
134
 
                // TODO: May need to investigate to see if the GUID needs to be stored in simias in a different
135
 
                // format.
136
 
                private string BuildGuidFilter( string guid )
137
 
                {
138
 
                        string guidFilter = string.Format( "(uid={0})", guid );
139
 
                        return guidFilter;
140
 
                }
141
 
 
142
 
                private string GetLdapGuid( LdapEntry entry )
143
 
                {
144
 
                        string ldapGuid = null;
145
 
 
146
 
                        try
147
 
                        {
148
 
                                LdapAttribute guidAttr = entry.getAttribute( "uid" );
149
 
                                if ( guidAttr != null && guidAttr.StringValue.Length != 0 )
150
 
                                {
151
 
                                        ldapGuid = guidAttr.StringValue;
152
 
                                }
153
 
                        }
154
 
                        catch{}
155
 
 
156
 
                        return ldapGuid;
157
 
                }
158
 
 
159
 
                private bool IsUser( String[] objectClasses )
160
 
                {
161
 
                        try
162
 
                        {
163
 
                                foreach( string s in objectClasses )
164
 
                                {
165
 
                                        string lower = s.ToLower();
166
 
                                        if ( lower == "inetorgperson" )
167
 
                                        {
168
 
                                                return true;
169
 
                                        }
170
 
                                }
171
 
                        }
172
 
                        catch( Exception e )
173
 
                        {
174
 
                                log.Error( "IsUser failed with exception" );
175
 
                                log.Error( e.Message );
176
 
                        }
177
 
                        return false;
178
 
                }
179
 
 
180
 
                private bool IsGroup( String[] objectClasses )
181
 
                {
182
 
                        try
183
 
                        {
184
 
                                foreach( string s in objectClasses )
185
 
                                {
186
 
                                        if ( s.ToLower() == "groupofnames" )
187
 
                                        {
188
 
                                                return true;
189
 
                                        }
190
 
                                }
191
 
                        }
192
 
                        catch( Exception e )
193
 
                        {
194
 
                                log.Error( "IsGroup failed with exception" );
195
 
                                log.Error( e.Message );
196
 
                        }
197
 
                        return false;
198
 
                }
199
 
 
200
 
                private bool IsContainer( String[] objectClasses )
201
 
                {
202
 
                        bool isContainer = false;
203
 
 
204
 
                        try
205
 
                        {
206
 
                                foreach( string s in objectClasses )
207
 
                                {
208
 
                                        string lower = s.ToLower();
209
 
                                        if ( lower == "organization" )
210
 
                                        {
211
 
                                                log.Debug( "Processing Organization Object..." );
212
 
                                                isContainer = true;
213
 
                                                break;
214
 
                                        }
215
 
                                        else if ( lower == "organizationalunit" )
216
 
                                        {
217
 
                                                isContainer = true;
218
 
                                                log.Debug( "Processing OrganizationalUnit Object..." );
219
 
                                                break;
220
 
                                        }
221
 
                                        else if ( lower == "country" )
222
 
                                        {
223
 
                                                isContainer = true;
224
 
                                                log.Debug( "Processing Country Object..." );
225
 
                                                break;
226
 
                                        }
227
 
                                        else if ( lower == "locality" )
228
 
                                        {
229
 
                                                isContainer = true;
230
 
                                                log.Debug( "Processing Locality Object..." );
231
 
                                                break;
232
 
                                        }
233
 
                                        else if ( lower == "dcobject" )
234
 
                                        {
235
 
                                                isContainer = true;
236
 
                                                log.Debug( "Processing DomainComponent Object..." );
237
 
                                                break;
238
 
                                        }
239
 
                                }
240
 
                        }
241
 
                        catch( Exception e )
242
 
                        {
243
 
                                log.Error( "IsContainer failed with exception" );
244
 
                                log.Error( e.Message );
245
 
                        }
246
 
 
247
 
                        return isContainer;
248
 
                }
249
 
 
250
 
                private void ProcessSearchUser( LdapConnection connection, String searchUser )
251
 
                {
252
 
                        // Since the first version of the iFolder 3.0 only
253
 
                        // exposes a username, firstname, lastname and full
254
 
                        // name, we'll limit the scope of the search
255
 
                        string[] searchAttributes = {   
256
 
                                                                                        "modifytimestamp",
257
 
                                                                                        ldapSettings.NamingAttribute,
258
 
                                                                                        "cn",
259
 
                                                                                        "sn", 
260
 
                                                                                        "uid",
261
 
                                                                                        "givenName", 
262
 
                                                                                        "ou" };
263
 
 
264
 
                        log.Debug( "ProcessSearchUser(" + searchUser + ")" );
265
 
 
266
 
                        try
267
 
                        {
268
 
                                LdapEntry ldapEntry = connection.Read( searchUser, searchAttributes );
269
 
                                ProcessUserEntry( ldapEntry );
270
 
                        }
271
 
                        catch( SimiasShutdownException s )
272
 
                        {
273
 
                                throw s;
274
 
                        }
275
 
                        catch( LdapException e )
276
 
                        {
277
 
                                log.Error( e.LdapErrorMessage );
278
 
                                log.Error( e.StackTrace );
279
 
                        }
280
 
                        catch( Exception e ) 
281
 
                        {
282
 
                                log.Error( e.Message );
283
 
                                log.Error( e.StackTrace );
284
 
                        }
285
 
                }
286
 
 
287
 
                // If the configured Simias Admin is different than the SimiasAdmin
288
 
                // identified in the store, make all the changes necessary to
289
 
                // make the configured admin the store admin.
290
 
                private void ChangeSimiasAdmin( LdapConnection conn )
291
 
                {
292
 
                        char[] dnDelimiters = {',', '='};
293
 
                        LdapEntry entry = null;
294
 
                        Property dn;
295
 
                        string commonName;
296
 
                        string ldapGuid;
297
 
                        string[] searchAttributes = { "cn", "sn", "uid" };
298
 
 
299
 
                        try
300
 
                        {
301
 
                                // Nothing in the config for a SimiasAdmin - we're done here
302
 
                                if ( ldapSettings.AdminDN == null || ldapSettings.AdminDN == "" )
303
 
                                {
304
 
                                        return;
305
 
                                }
306
 
 
307
 
                                // If the SimiasAdmin has been changed in the Simias.config, which BTW
308
 
                                // is not something that is exposed in the normal management UI, 
309
 
                                // we need to verify the new SimiasAdmin exists in the directory,
310
 
                                // check if the new admin exists in local domain memberlist (and
311
 
                                // if he doesn't create him), transfer default domain ownership
312
 
                                // to the new SimiasAdmin and lastly transfer ownership of all
313
 
                                // orphaned iFolders to the new SimiasAdmin.
314
 
 
315
 
                                try
316
 
                                {
317
 
                                        entry = conn.Read( OpenSync.ldapSettings.AdminDN, searchAttributes );
318
 
                                }
319
 
                                catch( LdapException lEx )
320
 
                                {
321
 
                                        log.Error( "Could not verify the newly configured Simias Administrator in the directory" );
322
 
                                        log.Error( lEx.Message );
323
 
                                }
324
 
                                catch( Exception e1 )
325
 
                                {
326
 
                                        log.Error( "Could not verify the newly configured Simias Administrator in the directory" );
327
 
                                        log.Error( e1.Message );
328
 
                                }
329
 
 
330
 
                                if ( entry == null )
331
 
                                {
332
 
                                        return;
333
 
                                }
334
 
 
335
 
                                ldapGuid = GetLdapGuid( entry );
336
 
                                if ( ldapGuid == null || ldapGuid == "" )
337
 
                                {
338
 
                                        return;
339
 
                                }
340
 
 
341
 
                                // Get the common name from the Simias.config.AdminDN entry
342
 
                                string[] components = OpenSync.ldapSettings.AdminDN.Split( dnDelimiters );
343
 
                                commonName = ( components[0].ToLower() == "cn" ) ? components[1] : components[0];
344
 
                                if ( commonName == null || commonName == "" )
345
 
                                {
346
 
                                        return;
347
 
                                }
348
 
 
349
 
                                store = Store.GetStore();
350
 
                                if ( domain == null )
351
 
                                {
352
 
                                        domain = store.GetDomain( store.DefaultDomain );
353
 
                                        if ( domain == null )
354
 
                                        {
355
 
                                                throw new SimiasException( "Enterprise domain does not exist!" );
356
 
                                        }
357
 
                                }
358
 
 
359
 
                                Member member = domain.GetMemberByName( commonName );
360
 
                                if ( member == null )
361
 
                                {
362
 
                                        // Create the member with the Ldap guid
363
 
                                        member = 
364
 
                                                new Member(     commonName,     ldapGuid, Simias.Storage.Access.Rights.ReadOnly );
365
 
                                        member.Properties.ModifyProperty( "DN", ldapSettings.AdminDN );
366
 
                                }
367
 
 
368
 
                                Property lguid = new Property( "LdapGuid", ldapGuid );
369
 
                                lguid.LocalProperty = true;
370
 
                                member.Properties.ModifyProperty( lguid );
371
 
                                domain.Commit( member );
372
 
 
373
 
                                // Transfer ownership of all collections owned by the 
374
 
                                // previous admin that have the orphaned property
375
 
                                Property orphaned;
376
 
                                ICSList subList = store.GetCollectionsByOwner( domain.Owner.ID, domain.ID ); 
377
 
                                foreach ( ShallowNode sn in subList )
378
 
                                {
379
 
                                        // Get the collection object for this node.
380
 
                                        Collection c = store.GetCollectionByID( sn.CollectionID );
381
 
                                        if ( c != null )
382
 
                                        {
383
 
                                                orphaned = c.Properties.GetSingleProperty( "OrphanedOwner" );
384
 
                                                if ( orphaned != null )
385
 
                                                {
386
 
                                                        dn = c.Owner.Properties.GetSingleProperty( "DN" );
387
 
                                                        if ( dn != null )
388
 
                                                        {
389
 
                                                                c.PreviousOwner = dn.Value.ToString();
390
 
                                                                c.Commit();
391
 
                                                        }
392
 
 
393
 
                                                        c.Commit( c.ChangeOwner( member, Simias.Storage.Access.Rights.ReadWrite ) );
394
 
                                                }
395
 
                                        }
396
 
                                }
397
 
 
398
 
                                // For now I'm just going to leave the LdapGuid property
399
 
                                // on the old SimiasAdmin
400
 
                                dn = domain.Owner.Properties.GetSingleProperty( "DN" );
401
 
                                if ( dn != null )
402
 
                                {
403
 
                                        domain.PreviousOwner = dn.Value.ToString();
404
 
                                        domain.Commit();
405
 
                                }
406
 
                                
407
 
                                domain.Commit( domain.ChangeOwner( member, Simias.Storage.Access.Rights.ReadWrite ) );
408
 
                        }
409
 
                        catch( Exception vsa )
410
 
                        {
411
 
                                log.Error( vsa.Message );
412
 
                                log.Error( vsa.StackTrace );
413
 
                        }
414
 
                }
415
 
 
416
 
                // The SimiasAdmin is processed differently than normal simias users because
417
 
                // the account is aleady created in the Simias store before LdapSync runs
418
 
                // so the GUID has already been created.  The SimiasAdmin must always exist in the
419
 
                // store and the DN entry in the store must be correct with the Distinguished
420
 
                // Name in the directory.  LdapSync counts on the AdminDN entry in Simias.config
421
 
                // to be updated if the admin is moved in the directory.
422
 
                private void ProcessSimiasAdmin( LdapConnection conn )
423
 
                {
424
 
                        // Since the first version of the iFolder 3.0 only
425
 
                        // exposes a username, firstname, lastname and full
426
 
                        // name, we'll limit the scope of the search
427
 
                        string[] searchAttributes = {   
428
 
                                                                                        "modifytimestamp",
429
 
                                                                                        ldapSettings.NamingAttribute,
430
 
                                                                                        "cn", 
431
 
                                                                                        "sn", 
432
 
                                                                                        "uid",
433
 
                                                                                        "givenName" }; 
434
 
 
435
 
                        char[] dnDelimiters = {',', '='};
436
 
                        LdapEntry entry = null;
437
 
                        LdapAttribute timeStampAttr = null;
438
 
                        Member cMember = null;
439
 
                        Property dn = null;
440
 
                        string ldapGuid = null;
441
 
 
442
 
                        log.Debug( "ProcessSimiasAdmin( " + ldapSettings.AdminDN + ")" );
443
 
 
444
 
                        string namingContext = "";
445
 
                        entry = conn.Read( "", new string[] { "namingContexts" } );
446
 
                        if ( entry != null )
447
 
                        {
448
 
                                namingContext = entry.getAttribute( "namingContexts" ).StringValue;
449
 
                        }
450
 
 
451
 
                        if ( domain == null )
452
 
                        {
453
 
                                store = Store.GetStore();
454
 
                                domain = store.GetDomain( store.DefaultDomain );
455
 
                                if ( domain == null )
456
 
                                {
457
 
                                        throw new SimiasException( "Enterprise domain does not exist!" );
458
 
                                }
459
 
                        }
460
 
 
461
 
                        // If the DN property has never been set on the SimiasAdmin,
462
 
                        // set it now
463
 
                        cMember = domain.Owner;
464
 
                        dn = cMember.Properties.GetSingleProperty( "DN" );
465
 
                        if ( dn == null || dn.Value.ToString() == "" )
466
 
                        {
467
 
                                if ( ldapSettings.AdminDN != null && ldapSettings.AdminDN != "" )
468
 
                                {
469
 
                                        dn = new Property( "DN", ldapSettings.AdminDN );
470
 
                                        cMember.Properties.ModifyProperty( dn );
471
 
                                }
472
 
                        }
473
 
 
474
 
                        // Check if the Simias Admin has changed in configuration
475
 
                        if ( ldapSettings.AdminDN != null && ldapSettings.AdminDN != "" &&
476
 
                                dn.Value.ToString() != ldapSettings.AdminDN )
477
 
                        {
478
 
                                ChangeSimiasAdmin( conn );
479
 
                                cMember = domain.Owner;
480
 
                        }
481
 
 
482
 
                        // The Simias admin is tracked in the directory by the directory
483
 
                        // guid.  Make sure the guid is stored in the node
484
 
                        Property lguidProp = cMember.Properties.GetSingleProperty( "LdapGuid" );
485
 
                        if ( lguidProp == null )
486
 
                        {
487
 
                                // This must be the first time thru so let's get the directory
488
 
                                // entry based on the configured DN
489
 
                                try
490
 
                                {
491
 
                                        entry = conn.Read( ldapSettings.AdminDN, searchAttributes );
492
 
                                }
493
 
                                catch( LdapException lEx )
494
 
                                {
495
 
                                        log.Error( "The Simias Administrator does not exist in the Ldap directory as configured in Simias.config!" );
496
 
                                        log.Error( lEx.Message );
497
 
                                }
498
 
                                catch( Exception e1 )
499
 
                                {
500
 
                                        log.Error( "The Simias Administrator does not exist in the Ldap directory as configured in Simias.config!" );
501
 
                                        log.Error( e1.Message );
502
 
                                }
503
 
 
504
 
                                if ( entry != null )
505
 
                                {
506
 
                                        ldapGuid = GetLdapGuid( entry );
507
 
                                        lguidProp = new Property( "LdapGuid", ldapGuid );
508
 
                                        lguidProp.LocalProperty = true;
509
 
                                        cMember.Properties.ModifyProperty( lguidProp );
510
 
                                }
511
 
                        }
512
 
                        else
513
 
                        {
514
 
                                ldapGuid = lguidProp.Value.ToString();
515
 
                        }
516
 
 
517
 
                        if ( ldapGuid != null )
518
 
                        {
519
 
                                try
520
 
                                {
521
 
                                        entry = null;
522
 
 
523
 
                                        // Now go find the SimiasAdmin in the Ldap directory
524
 
                                        string guidFilter = BuildGuidFilter( ldapGuid );
525
 
                                        LdapSearchResults results = 
526
 
                                                conn.Search(
527
 
                                                namingContext,
528
 
                                                LdapConnection.SCOPE_SUB, 
529
 
                                                "(&(objectclass=inetOrgPerson)" + guidFilter + ")",
530
 
                                                searchAttributes,
531
 
                                                false);
532
 
                                        if ( results.hasMore() == true )
533
 
                                        {
534
 
                                                entry = results.next();
535
 
                                        }
536
 
                                }
537
 
                                catch ( LdapException e )
538
 
                                {
539
 
                                        log.Error( e.LdapErrorMessage );
540
 
                                        log.Error( e.StackTrace );
541
 
                                }
542
 
                                catch ( Exception e )
543
 
                                {
544
 
                                        log.Error( e.Message );
545
 
                                        log.Error( e.StackTrace );
546
 
                                }
547
 
 
548
 
                                if ( entry != null )
549
 
                                {
550
 
                                        //
551
 
                                        // check if the ldap object's time stamp has changed
552
 
                                        //
553
 
                                        try
554
 
                                        {
555
 
                                                timeStampAttr = entry.getAttribute( "modifytimestamp" );
556
 
                                                Property pStamp = 
557
 
                                                        cMember.Properties.GetSingleProperty( "LdapTimeStamp" );
558
 
 
559
 
                                                if ( ( pStamp == null ) ||
560
 
                                                        ( pStamp != null && 
561
 
                                                        (string) pStamp.Value != timeStampAttr.StringValue ) )
562
 
                                                {
563
 
                                                        // The time stamp changed let's look at first and
564
 
                                                        // last name
565
 
        
566
 
                                                        try
567
 
                                                        {
568
 
                                                                bool changed = false;
569
 
        
570
 
                                                                // If we're tracking by ldap see if the naming attribute
571
 
                                                                // has changed
572
 
                                                                LdapAttribute namingAttr = entry.getAttribute( ldapSettings.NamingAttribute );
573
 
                                                                if ( namingAttr != null && namingAttr.StringValue.Length != 0 )
574
 
                                                                {
575
 
                                                                        if ( namingAttr.StringValue != cMember.Name )
576
 
                                                                        {
577
 
                                                                                cMember.Name = namingAttr.StringValue;
578
 
                                                                        }
579
 
                                                                }
580
 
        
581
 
                                                                LdapAttribute givenAttr = entry.getAttribute( "givenName" );
582
 
                                                                if ( givenAttr != null && givenAttr.StringValue.Length != 0 )
583
 
                                                                {
584
 
                                                                        if ( givenAttr.StringValue != cMember.Given )
585
 
                                                                        {
586
 
                                                                                changed = true;
587
 
                                                                                cMember.Given = givenAttr.StringValue;
588
 
                                                                        }
589
 
                                                                }
590
 
 
591
 
                                                                LdapAttribute sirAttr = entry.getAttribute( "sn" );
592
 
                                                                if ( sirAttr != null && sirAttr.StringValue.Length != 0 )
593
 
                                                                {
594
 
                                                                        if ( sirAttr.StringValue != cMember.Family )
595
 
                                                                        {
596
 
                                                                                cMember.Family = sirAttr.StringValue;
597
 
                                                                                changed = true;
598
 
                                                                        }
599
 
                                                                }
600
 
 
601
 
 
602
 
                                                                // If the entry has changed and we have a valid
603
 
                                                                // family and given
604
 
                                                                if ( changed == true && 
605
 
                                                                        cMember.Given != null &&
606
 
                                                                        cMember.Given != "" && 
607
 
                                                                        cMember.Family != null &&
608
 
                                                                        cMember.Family != "" )
609
 
                                                                {
610
 
                                                                        cMember.FN = cMember.Given + " " + cMember.Family;
611
 
                                                                }
612
 
 
613
 
                                                                // Did the distinguished name change?
614
 
                                                                Property dnProp = cMember.Properties.GetSingleProperty( "DN" );
615
 
                                                                if ( dnProp != null && ( dnProp.ToString() != entry.DN ) )
616
 
                                                                {
617
 
                                                                        dnProp.Value = entry.DN;
618
 
                                                                        cMember.Properties.ModifyProperty( "DN", dnProp );
619
 
                                                                }
620
 
                                                        }
621
 
                                                        catch {}
622
 
 
623
 
                                                        pStamp = new Property( "LdapTimeStamp", timeStampAttr.StringValue );
624
 
                                                        pStamp.LocalProperty = true;
625
 
                                                        cMember.Properties.ModifyProperty( pStamp );
626
 
                                                }
627
 
                                        }
628
 
                                        catch{}
629
 
                                }
630
 
                                else
631
 
                                {
632
 
                                        log.Error( "The Simias administrator could not be verified in the directory!" );
633
 
                                        log.Error( "Please update Simias.config with a valid Ldap user" );
634
 
                                }
635
 
                        }
636
 
                        else
637
 
                        {
638
 
                                log.Error( "The Simias administrator could not be verified in the directory!" );
639
 
                                log.Error( "Please update Simias.config with a valid Ldap user" );
640
 
                        }
641
 
 
642
 
                        // Now matter what always update the sync guid so
643
 
                        // the SimiasAdmin won't be deleted from Simias
644
 
 
645
 
                        cMember.Properties.ModifyProperty( state.SyncGuid );
646
 
                        domain.Commit( cMember );
647
 
                }
648
 
 
649
 
                private void ProcessSearchGroup( LdapConnection conn, String searchGroup )
650
 
                {
651
 
                        string[] searchAttributes = {
652
 
                                                                                        "objectClass",
653
 
                                                                                        "cn",
654
 
                                                                                        "member" };
655
 
 
656
 
                        log.Debug( "ProcessSearchGroup(" + searchGroup + ")" );
657
 
 
658
 
                        int count = 0;
659
 
 
660
 
                        try
661
 
                        {
662
 
                                LdapEntry ldapEntry = conn.Read( searchGroup, searchAttributes );
663
 
                                String[] members = ldapEntry.getAttribute("member").StringValueArray;
664
 
        
665
 
                                foreach( String member in members )
666
 
                                {
667
 
                                        // Check if the sync engine wants us to abort
668
 
                                        if ( this.abort == true )
669
 
                                        {
670
 
                                                return;
671
 
                                        }
672
 
 
673
 
                                        log.Debug( "   Processing member: " + member );
674
 
                                        count++;
675
 
                                        ProcessSearchUser( conn, member );
676
 
                                }
677
 
                        }
678
 
                        catch( SimiasShutdownException s )
679
 
                        {
680
 
                                throw s;
681
 
                        }
682
 
                        catch( LdapException e )
683
 
                        {
684
 
                                log.Error( e.LdapErrorMessage );
685
 
                                log.Error( e.StackTrace );
686
 
                        }
687
 
                        catch( Exception e )
688
 
                        {
689
 
                                log.Error( e.Message );
690
 
                                log.Error( e.StackTrace );
691
 
                        }
692
 
 
693
 
                        log.Debug( "Processed " + count.ToString() + " entries" );
694
 
                }
695
 
 
696
 
                private void ProcessSearchContainer(LdapConnection conn, String searchContainer)
697
 
                {
698
 
                        String searchFilter = "(objectclass=inetOrgPerson)";
699
 
                        string[] searchAttributes = {   
700
 
                                                                                        "modifytimestamp",
701
 
                                                                                        ldapSettings.NamingAttribute,
702
 
                                                                                        "cn", 
703
 
                                                                                        "sn", 
704
 
                                                                                        "uid",
705
 
                                                                                        "givenName", 
706
 
                                                                                        "ou" };
707
 
 
708
 
                        log.Debug( "ProcessSearchContainer(" + searchContainer + ")" );
709
 
 
710
 
                        int count = 0;
711
 
                        LdapSearchConstraints searchConstraints = new LdapSearchConstraints();
712
 
                        searchConstraints.MaxResults = 0;
713
 
 
714
 
                        LdapSearchQueue queue = 
715
 
                                conn.Search(
716
 
                                searchContainer, 
717
 
                                LdapConnection.SCOPE_SUB, 
718
 
                                searchFilter, 
719
 
                                searchAttributes, 
720
 
                                false,
721
 
                                (LdapSearchQueue) null,
722
 
                                searchConstraints);
723
 
 
724
 
                        LdapMessage ldapMessage;
725
 
                        while( ( ldapMessage = queue.getResponse() ) != null )
726
 
                        {
727
 
                                // Check if the sync engine wants us to abort
728
 
                                if ( this.abort == true )
729
 
                                {
730
 
                                        return;
731
 
                                }
732
 
 
733
 
                                if ( ldapMessage is LdapSearchResult )
734
 
                                {
735
 
                                        LdapEntry cEntry = ((LdapSearchResult) ldapMessage).Entry;
736
 
                                        if (cEntry == null)
737
 
                                        {
738
 
                                                continue;
739
 
                                        }
740
 
 
741
 
                                        try
742
 
                                        {
743
 
                                                ProcessUserEntry( cEntry );
744
 
                                                count++;
745
 
                                        }
746
 
                                        catch( SimiasShutdownException s )
747
 
                                        {
748
 
                                                log.Error( s.Message );
749
 
                                                throw s;
750
 
                                        }
751
 
                                        catch( LdapException e )
752
 
                                        {
753
 
                                                log.Error( "   Failed processing: " + cEntry.DN );
754
 
                                                log.Error( e.LdapErrorMessage );
755
 
                                                log.Error( e.StackTrace );
756
 
                                        }
757
 
                                        catch( Exception e )
758
 
                                        {
759
 
                                                log.Error( "   Failed processing: " + cEntry.DN );
760
 
                                                log.Error( e.Message );
761
 
                                                log.Error( e.StackTrace );
762
 
                                        }
763
 
                                }
764
 
                        }
765
 
 
766
 
                        log.Debug( "Processed " + count.ToString() + " entries" );
767
 
                }
768
 
 
769
 
                private void ProcessUserEntry( LdapEntry entry )
770
 
                {
771
 
                        log.Debug( "ProcessUserEntry(" + entry.DN + ")" );
772
 
 
773
 
                        string commonName = String.Empty;
774
 
                        string firstName = String.Empty;
775
 
                        string lastName = String.Empty;
776
 
                        string fullName = String.Empty;
777
 
                        string distinguishedName = String.Empty;
778
 
                        string ldapGuid = null;
779
 
 
780
 
                        char[] dnDelimiters = {',', '='};
781
 
                        LdapAttribute timeStampAttr = null;
782
 
 
783
 
                        bool attrError = false;
784
 
                        try
785
 
                        {
786
 
                                // get the last update time
787
 
                                timeStampAttr = entry.getAttribute( "modifytimestamp" );
788
 
 
789
 
                                ldapGuid = GetLdapGuid( entry );
790
 
                                distinguishedName = entry.DN;
791
 
 
792
 
                                // retrieve from configuration the directory attribute configured
793
 
                                // for naming in Simias.  
794
 
                                LdapAttribute cAttr = 
795
 
                                        entry.getAttribute( ldapSettings.NamingAttribute );
796
 
                                if ( cAttr != null && cAttr.StringValue.Length != 0 )
797
 
                                {
798
 
                                        commonName = cAttr.StringValue;
799
 
                                }
800
 
                                else
801
 
                                        if ( ldapSettings.NamingAttribute.ToLower() == LdapSettings.DefaultNamingAttribute.ToLower() )
802
 
                                {
803
 
                                        // If the naming attribute is default (cn) then we want to continue
804
 
                                        // to work the way we previously did so we don't break any existing installs.
805
 
                                        //
806
 
                                        // If the distinguishing attribute did not exist,
807
 
                                        // then make the Simias username the first component
808
 
                                        // of the ldap DN.
809
 
                                        string[] components = entry.DN.Split( dnDelimiters );
810
 
                                        commonName = components[1];
811
 
                                }
812
 
 
813
 
                                LdapAttribute givenAttr = entry.getAttribute( "givenName" );
814
 
                                if ( givenAttr != null && givenAttr.StringValue.Length != 0 )
815
 
                                {
816
 
                                        firstName = givenAttr.StringValue as string;
817
 
                                }
818
 
 
819
 
                                LdapAttribute sirAttr = entry.getAttribute( "sn" );
820
 
                                if ( sirAttr != null && sirAttr.StringValue.Length != 0 )
821
 
                                {
822
 
                                        lastName = sirAttr.StringValue as string;
823
 
                                }
824
 
 
825
 
                                if ( firstName != null && lastName != null )
826
 
                                {
827
 
                                        fullName = firstName + " " + lastName;
828
 
                                }
829
 
                        }
830
 
                        catch( Exception gEx )
831
 
                        {
832
 
                                log.Error( gEx.Message );
833
 
                                log.Error( gEx.StackTrace );
834
 
 
835
 
                                state.ReportError( gEx.Message );
836
 
                                attrError = true;
837
 
                        }
838
 
 
839
 
                        // No exception were generated gathering member info
840
 
                        // so call the sync engine to process this member
841
 
                        if ( attrError == false )
842
 
                        {
843
 
                                if ( timeStampAttr != null && timeStampAttr.StringValue.Length != 0 )
844
 
                                {
845
 
                                        Property ts = new Property( "LdapTimeStamp", timeStampAttr.StringValue );
846
 
                                        ts.LocalProperty = true;
847
 
                                        Property[] propertyList = { ts };
848
 
 
849
 
                                        state.ProcessMember(
850
 
                                                ldapGuid,
851
 
                                                commonName,
852
 
                                                firstName,
853
 
                                                lastName,
854
 
                                                fullName,
855
 
                                                distinguishedName,
856
 
                                                propertyList );
857
 
                                }
858
 
                                else
859
 
                                {
860
 
                                        state.ProcessMember(
861
 
                                                ldapGuid,
862
 
                                                commonName,
863
 
                                                firstName,
864
 
                                                lastName,
865
 
                                                fullName,
866
 
                                                distinguishedName,
867
 
                                                null );
868
 
                                }
869
 
                        }
870
 
                }
871
 
                
872
 
                #endregion
873
 
 
874
 
                #region Public Methods
875
 
                /// <summary>
876
 
                /// Call to abort an in process synchronization
877
 
                /// </summary>
878
 
                /// <returns>N/A</returns>
879
 
                public void Abort()
880
 
                {
881
 
                        abort = true;
882
 
                }
883
 
                
884
 
                /// <summary>
885
 
                /// Call to inform a provider to start a synchronization cycle
886
 
                /// </summary>
887
 
                /// <returns> True - provider successfully finished a sync cycle, 
888
 
                /// False - provider failed the sync cycle
889
 
                /// </returns>
890
 
                public bool Start( Simias.IdentitySync.State State )
891
 
                {
892
 
                        log.Debug( "Start called" );
893
 
 
894
 
                        bool status = false;
895
 
                        abort = false;
896
 
                        try
897
 
                        {
898
 
                                this.state = State;
899
 
 
900
 
                                try
901
 
                                {       
902
 
                                        ldapSettings = LdapSettings.Get( Store.StorePath );
903
 
                                        log.Debug( "new LdapConnection" );
904
 
                                        conn = new LdapConnection();
905
 
 
906
 
                                        log.Debug( "Connecting to: " + ldapSettings.Host + " on port: " + ldapSettings.Port.ToString() );
907
 
                                        conn.SecureSocketLayer = ldapSettings.SSL;
908
 
                                        conn.Connect( ldapSettings.Host, ldapSettings.Port );
909
 
 
910
 
                                        ProxyUser proxy = new ProxyUser();
911
 
 
912
 
                                        log.Debug( "Binding as: " + proxy.UserDN );
913
 
                                        conn.Bind( proxy.UserDN, proxy.Password );
914
 
 
915
 
                                        ProcessSimiasAdmin( conn );
916
 
                                        ProcessSearchObjects( conn, ldapSettings );
917
 
                                }
918
 
                                catch( SimiasShutdownException s )
919
 
                                {
920
 
                                        log.Error( s.Message );
921
 
                                        syncException = s;
922
 
                                        syncStatus = Simias.LdapProvider.Status.SyncThreadDown;
923
 
                                }
924
 
                                catch( LdapException e )
925
 
                                {
926
 
                                        log.Error( e.LdapErrorMessage );
927
 
                                        log.Error( e.StackTrace );
928
 
                                        syncException = e;
929
 
                                        syncStatus = 
930
 
                                                ( conn == null )
931
 
                                                ? Simias.LdapProvider.Status.LdapConnectionFailure
932
 
                                                : Simias.LdapProvider.Status.LdapAuthenticationFailure;
933
 
 
934
 
                                        state.ReportError( e.LdapErrorMessage );
935
 
                                }
936
 
                                catch(Exception e)
937
 
                                {
938
 
                                        log.Error( e.Message );
939
 
                                        log.Error( e.StackTrace );
940
 
                                        syncException = e;
941
 
                                        syncStatus = Simias.LdapProvider.Status.InternalException;
942
 
 
943
 
                                        state.ReportError( e.Message );
944
 
                                }
945
 
                                finally
946
 
                                {
947
 
                                        if ( conn != null )
948
 
                                        {
949
 
                                                log.Debug( "Disconnecting Ldap connection" );
950
 
                                                conn.Disconnect();
951
 
                                                conn = null;
952
 
                                        }
953
 
                                }       
954
 
                                status = true;
955
 
                        }
956
 
                        catch( Exception e )
957
 
                        {
958
 
                                log.Error( e.Message );
959
 
                                log.Error( e.StackTrace );
960
 
                                State.ReportError( e.Message );
961
 
                        }
962
 
                        
963
 
                        return status;
964
 
                }
965
 
                #endregion
966
 
        }
967
 
}