~ifolder-dev/simias/trunk-packaging

« back to all changes in this revision

Viewing changes to src/server/Simias.Server/.svn/text-base/HostProvider.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: Mike Lasky <mlasky@novell.com>
22
 
 |***************************************************************************/
23
 
 
24
 
using System;
25
 
using System.IO;
26
 
using System.Net;
27
 
using System.Xml;
28
 
using System.Security.Cryptography;
29
 
using System.Threading;
30
 
 
31
 
using Simias;
32
 
using Simias.Storage;
33
 
using Simias.Sync;
34
 
using Simias.Authentication;
35
 
using Simias.Client.Event;
36
 
using Simias.Server;
37
 
//using Simias.Provision;
38
 
 
39
 
namespace Simias.Host
40
 
{
41
 
        /// <summary>
42
 
        /// HostInfo class
43
 
        /// </summary>
44
 
        public class HostInfo
45
 
        {
46
 
                /// <summary>
47
 
                /// Host's unique ID
48
 
                /// </summary>
49
 
                public string ID;
50
 
 
51
 
                /// <summary>
52
 
                /// Host's name
53
 
                /// </summary>
54
 
                public string Name;
55
 
 
56
 
                /// <summary>
57
 
                /// Host's user/member ID which is consistent
58
 
                /// across all collections the host is 
59
 
                /// a member of.
60
 
                /// </summary>
61
 
                public string MemberID;
62
 
 
63
 
                /// <summary>
64
 
                /// External facing address for clients
65
 
                /// </summary>
66
 
                public string PublicAddress;
67
 
 
68
 
                /// <summary>
69
 
                /// Internal facing address for server to 
70
 
                /// server communication.
71
 
                /// </summary>
72
 
                public string PrivateAddress;
73
 
 
74
 
                /// <summary>
75
 
                /// Public key for host to host authentication
76
 
                /// </summary>
77
 
                public string PublicKey;
78
 
 
79
 
                /// <summary>
80
 
                /// true = Master, false = Slave
81
 
                /// </summary>
82
 
                public bool Master;
83
 
 
84
 
                /// <summary>
85
 
                /// HostInfo default constructor
86
 
                /// </summary>
87
 
                public HostInfo()
88
 
                {
89
 
                }
90
 
 
91
 
                internal HostInfo( HostNode node )
92
 
                {
93
 
                        ID = node.ID;
94
 
                        MemberID = node.UserID;
95
 
                        Name = node.Name;
96
 
                        PublicAddress = node.PublicUrl;
97
 
                        PrivateAddress = node.PrivateUrl;
98
 
                        PublicKey = node.PublicKey.ToXmlString( false );
99
 
                        Master = node.IsMasterHost;
100
 
                }
101
 
        }
102
 
 
103
 
        /// <summary>
104
 
        /// </summary>
105
 
        public class SlaveSetup
106
 
        {
107
 
                private static string tempHostFileName = ".host.xml";
108
 
                private static string tempPPKFileName = ".hostppk.xml";
109
 
                private static string tempDomainFileName = ".domain.xml";
110
 
                private static string tempOwnerFileName = ".owner.xml";
111
 
 
112
 
                private static void SaveXmlDoc( string storePath, string fileName, string sObject )
113
 
                {
114
 
                        string fullPath = Path.Combine( storePath, fileName );
115
 
                        StreamWriter stream = new StreamWriter( File.Open( fullPath, FileMode.Create, FileAccess.Write, FileShare.None ) );
116
 
                        stream.Write( sObject );
117
 
                        stream.Close();
118
 
                }
119
 
 
120
 
                private static string GetXmlDoc( string storePath, string fileName )
121
 
                {
122
 
                        string fullPath = Path.Combine( storePath, fileName );
123
 
                        StreamReader stream = new StreamReader( File.Open( fullPath, FileMode.Open, FileAccess.Read, FileShare.None ) );
124
 
                        string objectXml = stream.ReadToEnd();
125
 
                        stream.Close();
126
 
                        return objectXml;
127
 
                }
128
 
        
129
 
                internal static Domain GetDomain( string storePath )
130
 
                {
131
 
                        XmlDocument doc = new XmlDocument();
132
 
                        doc.LoadXml( GetXmlDoc( storePath, tempDomainFileName ) );
133
 
                        Domain domain = (Domain)Node.NodeFactory( Store.GetStore(), doc );
134
 
                        domain.Proxy = true;
135
 
                        return domain;
136
 
                }
137
 
 
138
 
                private static void SaveDomain( string storePath, string domain )
139
 
                {
140
 
                        SaveXmlDoc( storePath, tempDomainFileName, domain );
141
 
                }
142
 
 
143
 
                internal static Member GetOwner( string storePath )
144
 
                {
145
 
                        XmlDocument doc = new XmlDocument();
146
 
                        doc.LoadXml( GetXmlDoc( storePath, tempOwnerFileName ) );
147
 
                        Member owner = (Member)Node.NodeFactory( Store.GetStore(), doc );
148
 
                        owner.Proxy = true;
149
 
                        return owner;
150
 
                }
151
 
 
152
 
                private static void SaveOwner( string storePath, string owner )
153
 
                {
154
 
                        SaveXmlDoc( storePath, tempOwnerFileName, owner );
155
 
                }
156
 
 
157
 
                internal static HostNode GetHost( string storePath )
158
 
                {
159
 
                        XmlDocument doc = new XmlDocument();
160
 
                        doc.LoadXml( GetXmlDoc( storePath, tempHostFileName ) );
161
 
                        HostNode hnode = new HostNode( Node.NodeFactory( Store.GetStore(), doc ) );
162
 
                        return hnode;
163
 
                }
164
 
 
165
 
                private static void SaveHost( string storePath, string host )
166
 
                {
167
 
                        SaveXmlDoc( storePath, tempHostFileName, host );
168
 
                }
169
 
 
170
 
                internal static RSACryptoServiceProvider GetKeys( string storePath )
171
 
                {
172
 
                        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
173
 
                        string keys = GetXmlDoc( storePath, tempPPKFileName );
174
 
                        rsa.FromXmlString( keys );
175
 
                        return rsa;
176
 
                }
177
 
 
178
 
                /// <summary>
179
 
                /// </summary>
180
 
                public static RSACryptoServiceProvider CreateKeys( string storePath )
181
 
                {
182
 
                        try
183
 
                        {
184
 
                                RSACryptoServiceProvider rsa = GetKeys( storePath );
185
 
                                return rsa;
186
 
                        }
187
 
                        catch
188
 
                        {
189
 
                                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
190
 
                                return rsa;
191
 
                        }
192
 
                }
193
 
 
194
 
                /// <summary>
195
 
                /// </summary>
196
 
                public static void SaveInitObjects( string storePath, string domain, string owner, string host, RSACryptoServiceProvider rsa )
197
 
                {
198
 
                        SaveDomain( storePath, domain );
199
 
                        SaveOwner( storePath, owner );
200
 
                        SaveHost( storePath, host );
201
 
                        SaveXmlDoc( storePath, tempPPKFileName, rsa.ToXmlString( true ) );
202
 
                }
203
 
                                
204
 
                internal static void DeleteTempSetupFiles( string storePath )
205
 
                {
206
 
                        File.Delete( Path.Combine( storePath, tempDomainFileName ) );
207
 
                        File.Delete( Path.Combine( storePath, tempDomainFileName ) );
208
 
                        File.Delete( Path.Combine( storePath, tempHostFileName ) );
209
 
                        File.Delete( Path.Combine( storePath, tempPPKFileName ) );
210
 
                }
211
 
        }
212
 
 
213
 
        /// <summary>
214
 
        /// Summary description for HostDomainProvider.
215
 
        /// </summary>
216
 
        public class HostProvider
217
 
        {
218
 
                private Domain hostDomain;
219
 
                private HostNode host;
220
 
                private Store store = Store.GetStore();
221
 
                
222
 
                private static string ServerSection = "Server";
223
 
                private static string ServerNameKey = "Name";
224
 
                private static string PublicAddressKey = "PublicAddress";
225
 
                private static string PrivateAddressKey = "PrivateAddress";
226
 
                private static string MasterAddressKey = "MasterAddress";
227
 
                /// <summary>
228
 
                /// The ID of the Host domain. used for Host to Host authentication.
229
 
                /// </summary>
230
 
                private CollectionSyncClient syncClient;
231
 
                private AutoResetEvent syncEvent = new AutoResetEvent(false);
232
 
                private SimiasConnection connection;
233
 
                
234
 
                /// <summary>
235
 
                /// Construct a Host domain.
236
 
                /// </summary>
237
 
                /// <param name="domain">The enterprise domain.</param>
238
 
                public HostProvider( Domain domain )
239
 
                {
240
 
                        hostDomain = domain;
241
 
 
242
 
                        // Check if this is the master server.
243
 
                        bool master = ( hostDomain.Role == SyncRoles.Master ) ? true : false;
244
 
                        
245
 
                        // Get the HostDomain
246
 
                        // If the HostNode does not exist create it.
247
 
                        lock( typeof( HostProvider ) )
248
 
                        {
249
 
                                // Check if the host node exists.
250
 
                                string hName = Store.Config.Get( ServerSection, ServerNameKey );
251
 
 
252
 
                                // Make sure a master host can run without any pre-configured settings
253
 
                                // so if the public address wasn't configured get a non-loopback local
254
 
                                // address and configure the public address with it.
255
 
                                string publicAddress = Store.Config.Get( ServerSection, PublicAddressKey );
256
 
                                if ( publicAddress == null || publicAddress == String.Empty )
257
 
                                {
258
 
                                        // Get the first non-localhost address
259
 
                                        string[] addresses = MyDns.GetHostAddresses();
260
 
                                        foreach( string addr in addresses )
261
 
                                        {
262
 
                                                if ( IPAddress.IsLoopback( IPAddress.Parse( addr ) ) == false )
263
 
                                                {
264
 
                                                        publicAddress = addr;
265
 
                                                        break;
266
 
                                                }
267
 
                                        }
268
 
                                }
269
 
 
270
 
                                string privateAddress = Store.Config.Get( ServerSection, PrivateAddressKey );
271
 
                                if ( privateAddress == null || privateAddress == String.Empty )
272
 
                                {
273
 
                                        if ( publicAddress != null )
274
 
                                        {
275
 
                                                privateAddress = publicAddress;
276
 
                                        }
277
 
                                }
278
 
 
279
 
                                string masterAddress = Store.Config.Get( ServerSection, MasterAddressKey );
280
 
                                Member mNode = hostDomain.GetMemberByName( hName );
281
 
                                host = ( mNode == null ) ? null : new HostNode( mNode );
282
 
                                if ( host == null )
283
 
                                {
284
 
                                        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
285
 
                                        if( master == true )
286
 
                                        {
287
 
                                                host = new HostNode( hName, System.Guid.NewGuid().ToString(), publicAddress, privateAddress, rsa );
288
 
                                                host.Rights = Simias.Storage.Access.Rights.Admin;
289
 
                                                host.IsMasterHost = true;
290
 
                                        }
291
 
                                        else
292
 
                                        {
293
 
                                                host = SlaveSetup.GetHost( Store.StorePath );
294
 
                                                host.Proxy = true;
295
 
                                                rsa = SlaveSetup.GetKeys( Store.StorePath );
296
 
                                                // TODO remove
297
 
                                                Property p = new Property( PropertyTags.HostAddress, new Uri( masterAddress ) );
298
 
                                                p.LocalProperty = true;
299
 
                                                hostDomain.Properties.AddNodeProperty( p );
300
 
                                                // END TODO
301
 
                                        }
302
 
 
303
 
                                        host.IsLocalHost = true;
304
 
                                        hostDomain.Commit( new Node[] { hostDomain, host } );
305
 
                                        
306
 
                                        // Now Associate this host with the local identity.
307
 
                                        store.AddDomainIdentity( hostDomain.ID, host.UserID, rsa.ToXmlString(true), CredentialType.PPK );
308
 
                                        SlaveSetup.DeleteTempSetupFiles( Store.StorePath );
309
 
                                }
310
 
                                else
311
 
                                {
312
 
                                        // Make sure the address has not changed.
313
 
                                        bool hostChanged = false;
314
 
                                        if (host.PublicUrl != publicAddress)
315
 
                                        {
316
 
                                                host.PublicUrl = publicAddress;
317
 
                                                hostChanged = true;
318
 
                                        }
319
 
                                        if (host.PrivateUrl != privateAddress)
320
 
                                        {
321
 
                                                host.PrivateUrl = privateAddress;
322
 
                                                hostChanged = true;
323
 
                                        }
324
 
 
325
 
                                        if ( hostChanged == true )
326
 
                                        {
327
 
                                                hostDomain.Commit(host);
328
 
                                        }
329
 
                                }
330
 
                        }
331
 
 
332
 
                        if ( master == true )
333
 
                        {
334
 
                                // Register the ProvisionUser Provider.
335
 
                                ProvisionService.RegisterProvider( new LoadBalanceProvisionUserProvider() );
336
 
                                //ProvisionService.RegisterProvider( new MasterHostProvisionProvider() );
337
 
                        }
338
 
                        else
339
 
                        {
340
 
                                // Now start the sync process for the domain.
341
 
                                Thread syncThread = new Thread( new ThreadStart( SyncDomain ) );
342
 
                                syncThread.IsBackground = true;
343
 
                                syncThread.Start();
344
 
                        }
345
 
                }
346
 
 
347
 
                private void SyncDomain()
348
 
                {
349
 
                        int retry = 10;
350
 
                        while( true )
351
 
                        {
352
 
                                try
353
 
                                {
354
 
                                        // Get a connection object to the server.
355
 
                                        connection = new SimiasConnection( hostDomain.ID, host.UserID, SimiasConnection.AuthType.PPK, hostDomain );
356
 
 
357
 
                                        // We need to get a one time password to use to authenticate.
358
 
                                        connection.Authenticate();
359
 
                                        break;
360
 
                                }
361
 
                                catch
362
 
                                {
363
 
                                        Thread.Sleep( 10000 );
364
 
                                        if ( retry <= 0 )
365
 
                                        {
366
 
                                                break;
367
 
                                        }
368
 
                                }
369
 
                        }
370
 
                        
371
 
                        syncClient = new CollectionSyncClient( hostDomain.ID, new TimerCallback( TimerFired ) );
372
 
                        while ( true )
373
 
                        {
374
 
                                syncEvent.WaitOne();
375
 
                                try
376
 
                                {
377
 
                                        syncClient.SyncNow();
378
 
                                }
379
 
                                catch {}
380
 
                                syncClient.Reschedule( true, 30 );
381
 
                        }
382
 
                }
383
 
 
384
 
                /// <summary>
385
 
                /// Called by The CollectionSyncClient when it is time to run another sync pass.
386
 
                /// </summary>
387
 
                /// <param name="collectionClient">The client that is ready to sync.</param>
388
 
                public void TimerFired( object collectionClient )
389
 
                {
390
 
                        while(CollectionSyncClient.running)
391
 
                                Thread.Sleep(1000);
392
 
                        syncEvent.Set();
393
 
                }
394
 
        }
395
 
}