1
/****************************************************************************
3
| Copyright (c) 2007 Novell, Inc.
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.
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.
15
| You should have received a copy of the GNU General Public License
16
| along with this program; if not, contact Novell, Inc.
18
| To contact Novell about this file by physical or electronic mail,
19
| you may find current contact information at www.novell.com
22
|***************************************************************************/
25
using System.Collections;
26
using System.Security.Cryptography;
32
using Simias.Authentication;
34
namespace iFolder.WebService
37
/// An iFolder User Result Set
40
public class iFolderUserSet
43
/// An Array of iFolder Users
45
public iFolderUser[] Items;
48
/// The Total Number of iFolder Users
53
/// Default Constructor
55
public iFolderUserSet()
62
/// <param name="items"></param>
63
/// <param name="total"></param>
64
public iFolderUserSet(iFolderUser[] items, int total)
75
public class iFolderUser
78
/// Email Property Name
80
private static string EmailProperty = "Email";
82
private static readonly ISimiasLog log = SimiasLogManager.GetLogger(typeof(Member));
92
public string UserName;
95
/// The User Preferred Full Name
97
public string FullName;
100
/// The User First Name
102
public string FirstName;
105
/// The User Last Name
107
public string LastName;
109
/// The User Rights in the iFolder/Domain
111
public Rights MemberRights;
114
/// Is the User's Login Enabled
119
/// Is the User the Owner in the iFolder/Domain
124
/// The User Email Address
129
/// The User HomeServer Name
131
public string HomeServer;
141
/// Get an iFolder User Information Object.
143
/// <param name="member">The Member Object</param>
144
/// <param name="collection">The Collection Object</param>
145
/// <param name="domain">The Domain Object</param>
146
/// <returns>An iFolderUser Object</returns>
147
protected iFolderUser(Member member, Collection collection, Domain domain)
149
this.ID = member.UserID;
150
this.UserName = member.Name;
151
this.MemberRights = RightsUtility.Convert(member.Rights);
152
this.FullName = (member.FN != null) ? member.FN : member.Name;
153
this.FirstName = member.Given;
154
this.LastName = member.Family;
155
this.Enabled = !(domain.IsLoginDisabled(this.ID));
156
this.IsOwner = (member.UserID == collection.Owner.UserID);
157
this.Email = NodeUtility.GetStringProperty(member, EmailProperty);
159
if ( member.HomeServer != null )
160
this.HomeServer = (member.HomeServer.Name == null ) ? string.Empty : member.HomeServer.Name;
162
this.HomeServer = string.Empty;
164
// NOTE: The member object may not be complete if it did not come from the
166
if (collection != domain)
168
Member domainMember = domain.GetMemberByID(this.ID);
169
this.FullName = (domainMember.FN != null) ? domainMember.FN : domainMember.Name;
170
this.FirstName = domainMember.Given;
171
this.LastName = domainMember.Family;
172
this.Email = NodeUtility.GetStringProperty(member, EmailProperty);
179
/// <param name="userID">The User ID</param>
180
/// <param name="user">The iFolderUser object with updated fields.</param>
181
/// <param name="accessID">The Access User ID</param>
182
/// <returns>An updated iFolderUser Object</returns>
183
public static iFolderUser SetUser(string userID, iFolderUser user, string accessID)
185
Store store = Store.GetStore();
187
Domain domain = store.GetDomain(store.DefaultDomain);
190
iFolder.Impersonate(domain, accessID);
192
Member member = domain.GetMemberByID(userID);
194
// check username also
195
if (member == null) member = domain.GetMemberByName(userID);
198
if (member == null) throw new UserDoesNotExistException(userID);
201
member.FN = user.FullName;
202
member.Given = user.FirstName;
203
member.Family = user.LastName;
204
member.Properties.ModifyProperty(EmailProperty, user.Email);
206
// no full name policy
207
if (((user.FullName == null) || (user.FullName.Length == 0))
208
&& ((user.FirstName != null) && (user.FirstName.Length != 0))
209
&& ((user.LastName != null) && (user.LastName.Length != 0)))
211
member.FN = String.Format("{0} {1}", user.FirstName, user.LastName);
215
domain.Commit(member);
217
return GetUser(userID, accessID);
221
/// Get a Member of an iFolder
223
/// <param name="userID">The User ID</param>
224
/// <param name="accessID">The Access User ID</param>
225
/// <returns>An iFolderUser Object</returns>
226
public static iFolderUser GetUser(string userID, string accessID)
228
return GetUser(null, userID, accessID);
232
/// Get a Member of an iFolder
234
/// <param name="ifolderID">The iFolder ID</param>
235
/// <param name="userID">The User ID</param>
236
/// <param name="accessID">The Access User ID</param>
237
/// <returns>An iFolderUser Object</returns>
238
public static iFolderUser GetUser(string ifolderID, string userID, string accessID)
240
Store store = Store.GetStore();
242
Domain domain = store.GetDomain(store.DefaultDomain);
246
if (ifolderID == null)
248
// default to the domain
253
// get the collection
254
c = store.GetCollectionByID(ifolderID);
256
if (c == null) throw new iFolderDoesNotExistException(ifolderID);
260
iFolder.Impersonate(c, accessID);
262
Member member = c.GetMemberByID(userID);
264
// check username also
265
if (member == null) member = c.GetMemberByName(userID);
268
if (member == null) throw new UserDoesNotExistException(userID);
271
return new iFolderUser(member, c, domain);
275
/// Get the Members of an iFolder
277
/// <param name="ifolderID">The iFolder ID</param>
278
/// <param name="index">The Search Start Index</param>
279
/// <param name="max">The Search Max Count of Results</param>
280
/// <param name="accessID">The Access User ID</param>
281
/// <returns>An iFolder User Set</returns>
282
public static iFolderUserSet GetUsers(string ifolderID, int index, int max, string accessID)
284
Store store = Store.GetStore();
286
Domain domain = store.GetDomain(store.DefaultDomain);
290
if (ifolderID == null)
292
// default to the domain
297
// get the collection
298
c = store.GetCollectionByID(ifolderID);
300
if (c == null) throw new iFolderDoesNotExistException(ifolderID);
304
iFolder.Impersonate(c, accessID);
307
ICSList members = c.GetMemberList();
310
ArrayList sortList = new ArrayList();
312
foreach(ShallowNode sn in members)
319
// build the result list
320
ArrayList list = new ArrayList();
323
foreach(ShallowNode sn in sortList)
325
Member member = new Member(c, sn);
327
// Don't include the Host objects as iFolder users.
328
if (!member.IsType("Host"))
330
if ((i >= index) && (((max <= 0) || i < (max + index))))
332
Member tmpmember = domain.GetMemberByID(member.UserID);
334
list.Add(new iFolderUser(member, c, domain));
341
return new iFolderUserSet((iFolderUser[])list.ToArray(typeof(iFolderUser)), i);
345
/// Get Users by Search
347
/// <param name="property">The Search Property</param>
348
/// <param name="operation">The Search Operator</param>
349
/// <param name="pattern">The Search Pattern</param>
350
/// <param name="index">The Search Start Index</param>
351
/// <param name="max">The Search Max Count of Results</param>
352
/// <param name="accessID">The Access User ID</param>
353
/// <returns>An iFolder User Set</returns>
354
public static iFolderUserSet GetUsers(SearchProperty property, SearchOperation operation, string pattern, int index, int max, string accessID)
356
Store store = Store.GetStore();
358
Domain domain = store.GetDomain(store.DefaultDomain);
361
SearchOp searchOperation;
365
case SearchOperation.BeginsWith:
366
searchOperation = SearchOp.Begins;
369
case SearchOperation.EndsWith:
370
searchOperation = SearchOp.Ends;
373
case SearchOperation.Contains:
374
searchOperation = SearchOp.Contains;
377
case SearchOperation.Equals:
378
searchOperation = SearchOp.Equal;
382
searchOperation = SearchOp.Contains;
387
string searchProperty;
391
case SearchProperty.UserName:
392
searchProperty = BaseSchema.ObjectName;
395
case SearchProperty.FullName:
396
searchProperty = PropertyTags.FullName;
399
case SearchProperty.LastName:
400
searchProperty = PropertyTags.Family;
403
case SearchProperty.FirstName:
404
searchProperty = PropertyTags.Given;
408
searchProperty = PropertyTags.FullName;
413
iFolder.Impersonate(domain, accessID);
415
// create the search list
416
ICSList searchList = domain.Search(searchProperty, pattern, searchOperation);
418
// build the result list
419
ArrayList list = new ArrayList();
422
foreach(ShallowNode sn in searchList)
424
if (sn.IsBaseType(NodeTypes.MemberType))
426
Member member = new Member(domain, sn);
428
// Don't include Host objects as iFolder users.
429
if (!member.IsType("Host"))
431
if ((i >= index) && (((max <= 0) || i < (max + index))))
433
list.Add(new iFolderUser(member, domain, domain));
441
return new iFolderUserSet((iFolderUser[])list.ToArray(typeof(iFolderUser)), i);
445
/// Set the iFolder Rights of a Member
447
/// <param name="ifolderID">The iFolder ID</param>
448
/// <param name="userID">The Member User ID</param>
449
/// <param name="rights">The New Rights</param>
450
/// <param name="accessID">The Access User ID</param>
451
public static void SetMemberRights(string ifolderID, string userID, Rights rights, string accessID)
455
SharedCollection.SetMemberRights(ifolderID, userID, RightsUtility.Convert(rights).ToString(), accessID);
457
catch(CollectionStoreException e)
459
if (e.Message.IndexOf("change owner's rights") != -1)
461
throw new InvalidOperationException("The rights of the owner of the iFolder can not be changed.", e);
469
/// Add a Member to an iFolder
471
/// <param name="ifolderID">The iFolder ID</param>
472
/// <param name="userID">The User ID</param>
473
/// <param name="rights">The New Rights</param>
474
/// <param name="accessID">The Access User ID</param>
475
public static void AddMember(string ifolderID, string userID, Rights rights, string accessID)
479
SharedCollection.AddMember(ifolderID, userID, RightsUtility.Convert(rights).ToString(),
480
iFolder.iFolderCollectionType, accessID);
482
catch(ExistsException)
484
// ignore an already exists exception
489
/// Remove a Member from an iFolder
491
/// <param name="ifolderID">The iFolder ID</param>
492
/// <param name="userID">The User ID</param>
493
/// <param name="accessID">The Access User ID</param>
494
public static void RemoveMember(string ifolderID, string userID, string accessID)
498
SharedCollection.RemoveMember(ifolderID, userID, accessID);
502
// guess and improve exception
503
if (e.Message.IndexOf("iFolder owner") != -1)
505
throw new InvalidOperationException("The owner of an iFolder can not be removed.", e);
513
/// Se the Owner of an iFolder
515
/// <param name="ifolderID">The iFolder ID</param>
516
/// <param name="userID">The User ID</param>
517
/// <param name="accessID">The Access User ID</param>
518
public static void SetOwner(string ifolderID, string userID, string accessID, bool OrphanAdopt)
522
// check that the member exists
523
GetUser(ifolderID, userID, accessID);
527
// member does not exist
528
AddMember(ifolderID, userID, Rights.Admin, accessID);
531
// note: default the previous owner to "ReadOnly" rights
532
SharedCollection.ChangeOwner(ifolderID, userID, Access.Rights.ReadOnly.ToString(), accessID);
534
//If orphaned collection was adopted then delete the 'OrphanedOwner' property
537
Store store = Store.GetStore();
538
Collection c = store.GetCollectionByID(ifolderID);
539
if (c == null) throw new iFolderDoesNotExistException(ifolderID);
540
Property p = c.Properties.GetSingleProperty( "OrphanedOwner" );
543
c.Properties.DeleteSingleProperty( "OrphanedOwner" );
550
/// Is the User an Administrator
553
/// A User is a system administrator if the user has "Admin" rights in the domain.
555
/// <param name="userID">The User ID</param>
556
/// <returns>true, if the User is a System Administrator</returns>
557
public static bool IsAdministrator(string userID)
559
Store store = Store.GetStore();
561
Domain domain = store.GetDomain(store.DefaultDomain);
562
Member member = domain.GetMemberByID( userID );
563
Access.Rights rights = (member != null) ? member.Rights : Access.Rights.Deny;
565
return (rights == Access.Rights.Admin);
569
/// Give a User Administration Rights
572
/// A User is a system administrator if the user has "Admin" rights in the domain.
574
/// <param name="userID">The User ID</param>
575
public static void AddAdministrator(string userID)
577
Store store = Store.GetStore();
579
Domain domain = store.GetDomain(store.DefaultDomain);
581
SetMemberRights(domain.ID, userID, Rights.Admin, null);
585
/// Remove Administration Rights from a User
588
/// Administration rights are removed by giving the user "ReadOnly" rights in the domain.
590
/// <param name="userID">The User ID</param>
591
public static void RemoveAdministrator(string userID)
593
Store store = Store.GetStore();
595
Domain domain = store.GetDomain(store.DefaultDomain);
597
SetMemberRights(domain.ID, userID, Rights.ReadOnly, null);
601
/// Get the Administrators
603
/// <param name="index">The Search Start Index</param>
604
/// <param name="max">The Search Max Count of Results</param>
606
/// A User is a system administrator if the user has "Admin" rights in the domain.
608
/// <returns>An iFolder User Set</returns>
609
public static iFolderUserSet GetAdministrators(int index, int max)
611
Store store = Store.GetStore();
613
Domain domain = store.GetDomain(store.DefaultDomain);
615
ICSList members = domain.GetMembersByRights(Access.Rights.Admin);
618
ArrayList sortList = new ArrayList();
620
foreach(ShallowNode sn in members)
627
// build the result list
628
ArrayList list = new ArrayList();
631
foreach(ShallowNode sn in sortList)
633
Member member = new Member(domain, sn);
635
// Don't include Host objects as iFolder administrators.
636
if (!member.IsType("Host"))
638
if ((i >= index) && (((max <= 0) || i < (max + index))))
640
list.Add(new iFolderUser(member, domain, domain));
647
return new iFolderUserSet((iFolderUser[])list.ToArray(typeof(iFolderUser)), i);
653
///<returns></returns>
654
public static bool IsPassPhraseSet (string DomainID, string AccessID)
657
string CryptoKeyBlob = null;
660
Store store = Store.GetStore();
662
Collection collection = store.GetCollectionByID(DomainID);
663
Simias.Storage.Member member = collection.GetMemberByID(AccessID);
665
CryptoKeyBlob = member.ServerGetPassKeyHash();
669
log.Debug("IsPassPhraseSet : {0}", ex.Message);
672
log.Debug("IsPassPhraseSet :{0}", CryptoKeyBlob);
673
if(CryptoKeyBlob == String.Empty)
675
log.Debug("IsPassPhraseSet : false");
680
log.Debug("IsPassPhraseSet : true");
687
///Validate the passphrase for the correctness
689
///<returns>passPhrase.</returns>
690
public static Simias.Authentication.Status ValidatePassPhrase(string DomainID, string Passphrase, string AccessID)
692
string OldHash = null;
693
string NewHash = null;
697
Store store = Store.GetStore();
699
Collection collection = store.GetCollectionByID(DomainID);
700
Simias.Storage.Member member = collection.GetMemberByID(AccessID);
702
log.Debug("Member ValidatePassPhrase User:{0}...{1} ", member.Name, member.UserID);
704
log.Debug("ValidatePassPhrase : got PassKey");
705
string EncrypCryptoKey = member.ServerGetEncrypPassKey();
706
log.Debug("ValidatePassPhrase : got PassKey:{0}",EncrypCryptoKey);
708
//Hash the passphrase and use it for encryption and decryption
709
PassphraseHash hash = new PassphraseHash();
710
byte[] passphrase = hash.HashPassPhrase(Passphrase);
713
string DecryptedCryptoKey;
714
Key DeKey = new Key(EncrypCryptoKey);
715
DeKey.DecrypytKey(passphrase, out DecryptedCryptoKey);
717
//Encrypt using passphrase
718
string EncryptedCryptoKey;
719
Key EnKey = new Key(DecryptedCryptoKey);
720
EnKey.EncrypytKey(passphrase, out EncryptedCryptoKey);
723
Key HashKey = new Key(EncryptedCryptoKey);
724
NewHash = HashKey.HashKey();
726
OldHash = member.ServerGetPassKeyHash();
727
log.Debug("ValidatePassPhrase : getting OldHash:{0}", OldHash);
731
log.Debug("ValidatePassPhrase : {0}", ex.Message);
736
log.Debug("ValidatePassPhrase : Comparing blobs {0}...{1}",OldHash, NewHash);
737
if(String.Equals(OldHash, NewHash)==true)
739
log.Debug("ValidatePassPhrase : true");
740
return new Simias.Authentication.Status(Simias.Authentication.StatusCodes.Success);
744
log.Debug("ValidatePassPhrase : false");
745
return new Simias.Authentication.Status(Simias.Authentication.StatusCodes.PassPhraseInvalid);
750
///Set the passphrase and recovery agent
752
///<returns>passPhrase.</returns>
753
public static void SetPassPhrase(string DomainID, string Passphrase, string RAName, string RAPublicKey, string AccessID)
757
if(RAPublicKey != null && RAPublicKey != "" && RAName != null && RAName != "")
759
byte [] key = Convert.FromBase64String(RAPublicKey);
760
if(key.Length > 64 && key.Length < 128) //remove the 5 byte header and 5 byte trailer
762
byte[] NewKey = new byte[key.Length-10];
763
Array.Copy(key, 5, NewKey, 0, key.Length-10);
764
RAPublicKey = Convert.ToBase64String(NewKey);
766
else if(key.Length > 128 && key.Length < 256) //remove the 7 byte header and 5 byte trailer
768
byte[] NewKey = new byte[key.Length-12];
769
Array.Copy(key, 7, NewKey, 0, key.Length-12);
770
RAPublicKey = Convert.ToBase64String(NewKey);
772
else if(key.Length > 256) //remove the 9 byte header and 5 byte trailer
774
byte[] NewKey = new byte[key.Length-14];
775
Array.Copy(key, 9, NewKey, 0, key.Length-14);
776
RAPublicKey = Convert.ToBase64String(NewKey);
780
log.Debug("KeyCorrection RAName: {0}", RAName);
781
log.Debug("KeyCorrection RAPublicKey: {0}", RAPublicKey);
782
log.Debug("KeyCorrection key.Length: {0}", key.Length);
783
throw new SimiasException("Recovery key size not suported");
789
Store store = Store.GetStore();
791
Collection collection = store.GetCollectionByID(DomainID);
792
Simias.Storage.Member member = collection.GetMemberByID(AccessID);
794
//Hash the passphrase and use it for encryption and decryption
795
PassphraseHash hash = new PassphraseHash();
796
byte[] passphrase = hash.HashPassPhrase(Passphrase);
798
Key RAkey = new Key((passphrase.Length)*8);
799
string EncrypCryptoKey;
800
RAkey.EncrypytKey(passphrase, out EncrypCryptoKey);
801
Key HashKey = new Key(EncrypCryptoKey);
803
log.Debug("SetPassPhrase {0}...{1}...{2}...{3}",EncrypCryptoKey, HashKey.HashKey(), RAName, RAPublicKey);
804
member.ServerSetPassPhrase(EncrypCryptoKey, HashKey.HashKey(), RAName, RAPublicKey);
808
log.Debug("SetPassPhrase : {0}", ex.Message);