Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

646 lines
20 KiB

  1. using System;
  2. using System.Net;
  3. using System.Collections;
  4. using System.Data;
  5. using System.IO;
  6. using System.Security.Principal;
  7. using System.Security.Cryptography.X509Certificates;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Xml;
  11. using System.Xml.Schema;
  12. using System.Xml.Serialization;
  13. using System.Web.Services;
  14. using System.Web.Services.Description;
  15. using System.Web.Services.Protocols;
  16. using UDDI;
  17. using UDDI.Replication;
  18. using UDDI.Diagnostics;
  19. namespace UDDI.Tools
  20. {
  21. public class ReplicationConfigurationUtility
  22. {
  23. private static string executable = System.AppDomain.CurrentDomain.FriendlyName;
  24. private static string filename = null;
  25. private static string operatorKey = null;
  26. private static string rcfFile = null;
  27. private static bool overwrite = false;
  28. private enum ModeType
  29. {
  30. None = 0,
  31. ImportOperatorCertificate = 1,
  32. ExportOperatorCertificate = 2,
  33. ImportRCF = 3
  34. }
  35. private static ModeType mode = ModeType.None;
  36. /// ****************************************************************
  37. /// internal ProcessCommandLine [static]
  38. /// ----------------------------------------------------------------
  39. /// <summary>
  40. /// Parse the command-line.
  41. /// </summary>
  42. /// ----------------------------------------------------------------
  43. /// <param name="args">
  44. /// Command-line arguments.
  45. /// </param>
  46. /// ****************************************************************
  47. internal static void ProcessCommandLine( string[] args )
  48. {
  49. int i = 0;
  50. while( i < args.Length )
  51. {
  52. if( '-' == args[i][0] || '/' == args[i][0] )
  53. {
  54. //
  55. // Process the switch.
  56. //
  57. switch( args[i].Substring( 1 ).ToLower() )
  58. {
  59. case "i":
  60. if( i == args.Length - 1 )
  61. throw new CommandLineException( "Missing required argument 'certfile'." );
  62. mode = ModeType.ImportOperatorCertificate;
  63. i ++;
  64. filename = args[i];
  65. if( !File.Exists( filename ) )
  66. throw new CommandLineException( "Certificate file '" + filename + "' does not exist." );
  67. break;
  68. case "e":
  69. if( i == args.Length - 1 )
  70. throw new CommandLineException( "Missing required argument 'certfile'." );
  71. mode = ModeType.ExportOperatorCertificate;
  72. i ++;
  73. filename = args[i];
  74. break;
  75. case "o":
  76. if( i == args.Length - 1 )
  77. throw new CommandLineException( "Missing required argument 'operatorkey'." );
  78. i ++;
  79. operatorKey = args[i];
  80. //
  81. // strip {'s and }'s
  82. //
  83. operatorKey = operatorKey.Replace("{", string.Empty);
  84. operatorKey = operatorKey.Replace("}", string.Empty);
  85. break;
  86. case "r":
  87. if( i == args.Length - 1 )
  88. {
  89. throw new CommandLineException( "Missing required argument 'path to RCF file'." );
  90. }
  91. i ++;
  92. rcfFile = args[i];
  93. mode = ModeType.ImportRCF;
  94. if( !File.Exists( rcfFile ) )
  95. throw new CommandLineException( "RCF file '" + rcfFile + "' does not exist." );
  96. break;
  97. case "y":
  98. overwrite = true;
  99. break;
  100. case "?":
  101. goto case "help";
  102. case "help":
  103. throw new CommandLineException( "" );
  104. default:
  105. throw new CommandLineException( "Unknown command-line parameter '" + args[i] + "'." );
  106. }
  107. }
  108. i ++;
  109. }
  110. //
  111. // Make sure the appropriate options were set.
  112. //
  113. //if()
  114. // throw new CommandLineException( "Missing required command-line parameters." );
  115. }
  116. public static void ImportOperatorCertificate()
  117. {
  118. X509Certificate certificate = X509Certificate.CreateFromCertFile( filename );
  119. SaveOperatorInfo( operatorKey, certificate );
  120. }
  121. public static void ImportRCF()
  122. {
  123. FileStream rcfStream = File.Open( rcfFile, FileMode.Open, FileAccess.Read, FileShare.Read );
  124. try
  125. {
  126. //
  127. // Validate the RCF file.
  128. //
  129. SchemaCollection.Validate( rcfStream );
  130. //
  131. //
  132. // Open our RCF file, it has already been checked to make sure it exists.
  133. //
  134. XmlTextReader rcfReader = new XmlTextReader( rcfStream );
  135. while( true == rcfReader.Read() && false == rcfReader.EOF )
  136. {
  137. if( rcfReader.Name.Equals( "operator" ) && rcfReader.NamespaceURI.Equals( UDDI.Replication.Constants.Namespace ) )
  138. {
  139. //
  140. // For each operator node, we want the following information. These are all
  141. // mandatory elements, so if any were missing we should not have passed schema
  142. // validation.
  143. //
  144. // operatorNodeID (this is the operatorKey)
  145. // operatorStatus
  146. // soapReplicationUrl
  147. // certificate
  148. // operatorCustodyName (operatorName)
  149. //
  150. //
  151. // Note that contacts are currently being ignored. This is because we are not sending
  152. // the businessKey for the operator. Since we store contacts based on businessKey (actually businessID)
  153. // we do not have a way of storing contacts. IN 70 says that the operatorNodeID should actually be this
  154. // businessKey, so once we decide to implement this, we'll process contacts.
  155. //
  156. X509Certificate certificate = null;
  157. string operatorKey = null;
  158. string operatorName = null;
  159. string soapReplicationUrl = null;
  160. int operatorStatus = 0;
  161. string localOperatorKey = Config.GetString( "OperatorKey" ).ToLower();
  162. do
  163. {
  164. switch( rcfReader.Name )
  165. {
  166. case "operatorNodeID":
  167. {
  168. operatorKey = rcfReader.ReadElementString();
  169. break;
  170. }
  171. case "operatorCustodyName":
  172. {
  173. operatorName = rcfReader.ReadElementString();
  174. break;
  175. }
  176. case "operatorStatus":
  177. {
  178. operatorStatus = OperatorStatus2ID( rcfReader.ReadElementString() );
  179. break;
  180. }
  181. case "soapReplicationURL":
  182. {
  183. soapReplicationUrl = rcfReader.ReadElementString();
  184. break;
  185. }
  186. case "certificate":
  187. {
  188. //
  189. // Read our data in 1024 byte chunks. Keep an array list of these
  190. // chunks.
  191. //
  192. int bytesRead = 0;
  193. int chunkSize = 1024;
  194. ArrayList chunks = new ArrayList();
  195. do
  196. {
  197. byte[] data = new byte[ chunkSize ];
  198. bytesRead = rcfReader.ReadBase64( data, 0, chunkSize );
  199. if( bytesRead > 0 )
  200. {
  201. chunks.Add( data );
  202. }
  203. }while( bytesRead != 0 );
  204. //
  205. // Allocate a buffer to hold all of our chunks.
  206. //
  207. byte[] certificateData = new byte[ chunks.Count * chunkSize ];
  208. //
  209. // Copy each chunk into our buffer. This buffer is our certificate.
  210. //
  211. int index = 0;
  212. foreach( byte[] chunkData in chunks )
  213. {
  214. Array.Copy( chunkData, 0, certificateData, index, chunkData.Length );
  215. index += chunkData.Length;
  216. }
  217. //
  218. // Create a certificate from our byte data.
  219. //
  220. certificate = new X509Certificate( certificateData );
  221. break;
  222. }
  223. }
  224. }while( true == rcfReader.Read() && false == rcfReader.EOF && false == rcfReader.Name.Equals( "operator" ) );
  225. //
  226. // Make sure we identify the local operator.
  227. //
  228. if( false == operatorKey.ToLower().Equals( localOperatorKey ) )
  229. {
  230. //
  231. // Import this operator
  232. //
  233. SaveOperatorInfo( operatorKey, operatorName, soapReplicationUrl, operatorStatus, certificate );
  234. Console.WriteLine( "Successfully imported {0}.", operatorName );
  235. }
  236. else
  237. {
  238. SaveOperatorInfo( null, operatorName, soapReplicationUrl, operatorStatus, certificate );
  239. Console.WriteLine( "Successfully update the local operator." );
  240. }
  241. }
  242. }
  243. }
  244. catch( XmlException xmlException )
  245. {
  246. Console.WriteLine( "Exception processing the RCF: " );
  247. Console.WriteLine( "\t" );
  248. Console.WriteLine( xmlException.ToString() );
  249. }
  250. catch( XmlSchemaException schemaException )
  251. {
  252. Console.WriteLine( "The RCF did not pass schema validation: " );
  253. Console.WriteLine( "\t" );
  254. Console.WriteLine( schemaException.ToString() );
  255. }
  256. finally
  257. {
  258. rcfStream.Close();
  259. }
  260. }
  261. public static void ExportOperatorCertificate()
  262. {
  263. if( null == operatorKey )
  264. {
  265. operatorKey = Config.GetString( "OperatorKey" );
  266. }
  267. if( File.Exists( filename ) && !overwrite )
  268. {
  269. Console.Write( "Overwrite '{0}' [y/n]? ", filename );
  270. int choice = Console.Read();
  271. if( 'y' != (char)choice && 'Y' != (char)choice )
  272. {
  273. Console.WriteLine();
  274. Console.WriteLine( "Operation aborted." );
  275. return;
  276. }
  277. }
  278. byte[] data = null;
  279. //
  280. // Retrieve the certificate.
  281. //
  282. SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
  283. sp.ProcedureName = "net_operator_get";
  284. sp.Parameters.Add( "@operatorKey", SqlDbType.UniqueIdentifier );
  285. sp.Parameters.SetGuidFromString( "@operatorKey", operatorKey );
  286. SqlDataReaderAccessor reader = sp.ExecuteReader();
  287. try
  288. {
  289. if( reader.Read() )
  290. data = reader.GetBinary( "certificate" );
  291. }
  292. finally
  293. {
  294. reader.Close();
  295. }
  296. FileStream file = File.Open( filename, FileMode.Create, FileAccess.Write, FileShare.None );
  297. try
  298. {
  299. int filesize = (int)data.Length;
  300. file.Write( data, 0, filesize );
  301. Console.WriteLine( "Wrote {0} byte(s) to certificate file '{1}'.\r\nSource: {{{2}}}",
  302. filesize,
  303. filename,
  304. operatorKey );
  305. }
  306. finally
  307. {
  308. file.Close();
  309. }
  310. }
  311. private static int OperatorStatus2ID( string status )
  312. {
  313. //
  314. // These values must match the values in UDO_operatorStatus
  315. //
  316. int id = 2;
  317. switch( status )
  318. {
  319. case "disable":
  320. {
  321. id = 0;
  322. break;
  323. }
  324. case "new":
  325. {
  326. id = 1;
  327. break;
  328. }
  329. case "normal":
  330. {
  331. id = 2;
  332. break;
  333. }
  334. case "resigned":
  335. {
  336. id = 3;
  337. break;
  338. }
  339. }
  340. return id;
  341. }
  342. private static void SaveOperatorInfo( string operatorKey, X509Certificate certificate)
  343. {
  344. //
  345. // Default operator status to 2 (normal)
  346. //
  347. SaveOperatorInfo( operatorKey, operatorKey, null, 2, certificate );
  348. }
  349. private static void SaveOperatorInfo( string operatorKey,
  350. string operatorName,
  351. string soapReplicationUrl,
  352. int operatorStatus,
  353. X509Certificate certificate)
  354. {
  355. byte[] data = certificate.GetRawCertData();
  356. ConnectionManager.BeginTransaction();
  357. SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
  358. sp.ProcedureName = "net_operator_save";
  359. if( null == operatorKey )
  360. {
  361. //
  362. // Import a certificate for the local operator
  363. //
  364. operatorKey = Config.GetString( "OperatorKey" );
  365. sp.Parameters.Add( "@operatorKey", SqlDbType.UniqueIdentifier );
  366. sp.Parameters.Add( "@certSerialNo", SqlDbType.NVarChar, UDDI.Constants.Lengths.CertSerialNo );
  367. sp.Parameters.Add( "@certIssuer", SqlDbType.NVarChar, UDDI.Constants.Lengths.CertIssuer );
  368. sp.Parameters.Add( "@certSubject", SqlDbType.NVarChar, UDDI.Constants.Lengths.CertSubject );
  369. sp.Parameters.Add( "@certificate", SqlDbType.Image );
  370. sp.Parameters.SetGuidFromString( "@operatorKey", operatorKey );
  371. sp.Parameters.SetString( "@certSerialNo", certificate.GetSerialNumberString() );
  372. sp.Parameters.SetString( "@certIssuer", certificate.GetIssuerName() );
  373. sp.Parameters.SetString( "@certSubject", certificate.GetName() );
  374. sp.Parameters.SetBinary( "@certificate", data );
  375. sp.ExecuteNonQuery();
  376. }
  377. else
  378. {
  379. //
  380. // Create a new operator / publisher and import certificate
  381. //
  382. //
  383. // First add a publisher for the new operator
  384. //
  385. SqlStoredProcedureAccessor sp2 = new SqlStoredProcedureAccessor();
  386. sp2.ProcedureName = "UI_savePublisher";
  387. sp2.Parameters.Add( "@PUID", SqlDbType.NVarChar, UDDI.Constants.Lengths.UserID );
  388. sp2.Parameters.Add( "@name", SqlDbType.NVarChar, UDDI.Constants.Lengths.Name );
  389. sp2.Parameters.Add( "@email", SqlDbType.NVarChar, UDDI.Constants.Lengths.Email );
  390. //
  391. // TODO: use UDDI.Constants.Lengths.Phone when the UI_savePublisher is fixed
  392. //
  393. sp2.Parameters.Add( "@phone", SqlDbType.VarChar, 20 );
  394. sp2.Parameters.SetString( "@PUID", operatorKey );
  395. sp2.Parameters.SetString( "@name", operatorKey );
  396. sp2.Parameters.SetString( "@email", "" );
  397. sp2.Parameters.SetString( "@phone", "" );
  398. sp2.ExecuteNonQuery();
  399. //
  400. // Add the new operator and link it to the new publisher
  401. //
  402. sp.Parameters.Add( "@operatorKey", SqlDbType.UniqueIdentifier );
  403. sp.Parameters.Add( "@operatorStatusID", SqlDbType.Int );
  404. sp.Parameters.Add( "@PUID", SqlDbType.NVarChar, UDDI.Constants.Lengths.UserID );
  405. sp.Parameters.Add( "@name", SqlDbType.NVarChar, UDDI.Constants.Lengths.Name );
  406. sp.Parameters.Add( "@soapReplicationURL", SqlDbType.NVarChar, UDDI.Constants.Lengths.SoapReplicationURL );
  407. sp.Parameters.Add( "@certSerialNo", SqlDbType.NVarChar, UDDI.Constants.Lengths.CertSerialNo );
  408. sp.Parameters.Add( "@certIssuer", SqlDbType.NVarChar, UDDI.Constants.Lengths.CertIssuer );
  409. sp.Parameters.Add( "@certSubject", SqlDbType.NVarChar, UDDI.Constants.Lengths.CertSubject );
  410. sp.Parameters.Add( "@certificate", SqlDbType.Image );
  411. sp.Parameters.SetGuidFromString( "@operatorKey", operatorKey );
  412. sp.Parameters.SetInt( "@operatorStatusID", operatorStatus );
  413. sp.Parameters.SetString( "@PUID", operatorKey );
  414. sp.Parameters.SetString( "@name", operatorName );
  415. sp.Parameters.SetString( "@soapReplicationURL", soapReplicationUrl );
  416. sp.Parameters.SetString( "@certSerialNo", certificate.GetSerialNumberString() );
  417. sp.Parameters.SetString( "@certIssuer", certificate.GetIssuerName() );
  418. sp.Parameters.SetString( "@certSubject", certificate.GetName() );
  419. sp.Parameters.SetBinary( "@certificate", data );
  420. sp.ExecuteNonQuery();
  421. }
  422. ConnectionManager.Commit();
  423. Console.WriteLine( "Wrote {0} byte(s) to operator key {{{1}}}.\r\nSource: '{2}'.",
  424. data.Length,
  425. operatorKey,
  426. filename );
  427. }
  428. /// ****************************************************************
  429. /// public Main [static]
  430. /// ----------------------------------------------------------------
  431. /// <summary>
  432. /// Program entry point.
  433. /// </summary>
  434. /// ----------------------------------------------------------------
  435. /// <param name="args">
  436. /// Command-line arguments.
  437. /// </param>
  438. /// ****************************************************************
  439. ///
  440. public static void Main( string[] args )
  441. {
  442. try
  443. {
  444. ConnectionManager.Open( true, false );
  445. Debug.VerifySetting( "OperatorKey" );
  446. Console.WriteLine( "Microsoft (R) UDDI Replication Configuration Utility." );
  447. Console.WriteLine( "Copyright (C) Microsoft Corp. 2002. All rights reserved." );
  448. Console.WriteLine();
  449. WindowsIdentity identity = WindowsIdentity.GetCurrent();
  450. WindowsPrincipal principal = new WindowsPrincipal( identity );
  451. Context.User.SetRole( principal );
  452. if( !Context.User.IsAdministrator )
  453. {
  454. Console.WriteLine( "Access denied.\r\n\r\nThis program must be executed by a member of the '"
  455. + Config.GetString( "GroupName.Administrators" ) + "'\r\ngroup. The current user '"
  456. + identity.Name + "' is not a member of this group." );
  457. return;
  458. }
  459. ProcessCommandLine( args );
  460. switch( mode )
  461. {
  462. case ModeType.ImportOperatorCertificate:
  463. ImportOperatorCertificate();
  464. break;
  465. case ModeType.ExportOperatorCertificate:
  466. ExportOperatorCertificate();
  467. break;
  468. case ModeType.ImportRCF:
  469. ImportRCF();
  470. break;
  471. default:
  472. throw new CommandLineException( "" );
  473. }
  474. }
  475. catch( CommandLineException e )
  476. {
  477. //
  478. // Display command-line help.
  479. //
  480. Console.WriteLine( "Syntax:" );
  481. Console.WriteLine( " " + executable + " <options> [parameters]" );
  482. Console.WriteLine();
  483. Console.WriteLine( "Options:" );
  484. Console.WriteLine( " -help Displays this help message." );
  485. Console.WriteLine( " -i <certfile> Import a certificate. If the -o option is not" );
  486. Console.WriteLine( " used, the certificate is imported for the" );
  487. Console.WriteLine( " local operator." );
  488. Console.WriteLine( " -e <certfile> Export a certificate. If the -o option is not" );
  489. Console.WriteLine( " used, the certificate is exported from the" );
  490. Console.WriteLine( " local operator." );
  491. Console.WriteLine( " -o <operatorkey> The operator key to import/export a certificate" );
  492. Console.WriteLine( " Omit this parameter to import a certificate for the" );
  493. Console.WriteLine( " local operator." );
  494. Console.WriteLine( " -y Supress file overwrite prompt." );
  495. Console.WriteLine( " -r <rcf> Path to replication configuration file (RCF)." );
  496. Console.WriteLine();
  497. Console.WriteLine( "Examples:" );
  498. Console.WriteLine( " " + executable + " -help" );
  499. Console.WriteLine( " " + executable + " -o FF735874-28BD-41A0-96F3-02113FFD9D6C -i uddi.cer" );
  500. Console.WriteLine( " " + executable + " -i uddi.cer" );
  501. Console.WriteLine( " " + executable + " -r operators.xml" );
  502. Console.WriteLine();
  503. if( 0 != e.Message.Length )
  504. Console.WriteLine( e.Message );
  505. return;
  506. }
  507. catch( Exception e )
  508. {
  509. Console.WriteLine( e.ToString() );
  510. return;
  511. }
  512. }
  513. }
  514. /// ****************************************************************
  515. /// public class CommandLineException
  516. /// ----------------------------------------------------------------
  517. /// <summary>
  518. /// Exception class for errors encountered while parsing the
  519. /// command-line.
  520. /// </summary>
  521. /// ****************************************************************
  522. ///
  523. public class CommandLineException : ApplicationException
  524. {
  525. /// ************************************************************
  526. /// public CommandLineException [constructor]
  527. /// ------------------------------------------------------------
  528. /// <summary>
  529. /// CommandLineException constructor.
  530. /// </summary>
  531. /// ************************************************************
  532. ///
  533. public CommandLineException()
  534. : base()
  535. {
  536. }
  537. /// ************************************************************
  538. /// public CommandLineException [constructor]
  539. /// ------------------------------------------------------------
  540. /// <summary>
  541. /// CommandLineException constructor.
  542. /// </summary>
  543. /// ------------------------------------------------------------
  544. /// <param name="message">
  545. /// Exception message.
  546. /// </param>
  547. /// ************************************************************
  548. ///
  549. public CommandLineException( string message )
  550. : base( message )
  551. {
  552. }
  553. }
  554. }