1616using System . IO ;
1717using System . Linq ;
1818using System . Collections . Generic ;
19- using System . Runtime . ConstrainedExecution ;
2019using System . Security . Cryptography . X509Certificates ;
2120using System . Text ;
22- using System . Xml . Linq ;
2321using com . citrix . netscaler . nitro . exception ;
2422using com . citrix . netscaler . nitro . resource . Base ;
2523using com . citrix . netscaler . nitro . resource . config . ssl ;
2826using com . citrix . netscaler . nitro . util ;
2927using Keyfactor . Logging ;
3028using Keyfactor . Orchestrators . Extensions ;
29+ using Keyfactor . PKI . CryptographicObjects . Formatters ;
30+ using Keyfactor . PKI . PEM ;
31+ using Keyfactor . PKI . PrivateKeys ;
3132using Microsoft . Extensions . Logging ;
3233using Newtonsoft . Json ;
3334using Org . BouncyCastle . Crypto ;
3435using Org . BouncyCastle . OpenSsl ;
3536using Org . BouncyCastle . Pkcs ;
37+ using Keyfactor . Orchestrators . Common . Enums ;
3638
3739namespace Keyfactor . Extensions . Orchestrator . CitricAdc
3840{
3941 // ReSharper disable once InconsistentNaming
4042 internal class CitrixAdcStore
4143 {
42- private const uint Timeout = 3600 ;
44+ private const string DefaultTimeout = " 3600" ;
4345 public static readonly string StoreType = "CitrixAdc" ;
4446
4547 private readonly string _clientMachine ;
@@ -50,6 +52,7 @@ internal class CitrixAdcStore
5052 public readonly string StorePath ;
5153 private readonly string _username ;
5254 private readonly bool _useSsl ;
55+ private uint _timeout ;
5356
5457 private nitro_service _nss ;
5558
@@ -60,6 +63,8 @@ public CitrixAdcStore(InventoryJobConfiguration config, string serverUserName, s
6063 Logger = LogHandler . GetClassLogger < CitrixAdcStore > ( ) ;
6164 Logger . MethodEntry ( LogLevel . Debug ) ;
6265
66+ SetTimeout ( JsonConvert . DeserializeObject ( config . CertificateStoreDetails . Properties . ToString ( ) ) ) ;
67+
6368 _clientMachine = config . CertificateStoreDetails . ClientMachine ;
6469 StorePath = StripTrailingSlash ( config . CertificateStoreDetails . StorePath ) ;
6570 var o = new systemfile_args ( ) ;
@@ -93,6 +98,8 @@ public CitrixAdcStore(ManagementJobConfiguration config, string serverUserName,
9398 Logger = LogHandler . GetClassLogger < CitrixAdcStore > ( ) ;
9499 Logger . MethodEntry ( LogLevel . Debug ) ;
95100
101+ SetTimeout ( JsonConvert . DeserializeObject ( config . CertificateStoreDetails . Properties . ToString ( ) ) ) ;
102+
96103 _clientMachine = config . CertificateStoreDetails . ClientMachine ;
97104 StorePath = StripTrailingSlash ( config . CertificateStoreDetails . StorePath ) ;
98105 _useSsl = config . UseSSL ;
@@ -125,11 +132,14 @@ public CitrixAdcStore(ManagementJobConfiguration config, string serverUserName,
125132 public void Login ( )
126133 {
127134 Logger . MethodEntry ( LogLevel . Debug ) ;
135+ Logger . LogTrace ( $ "Timeout Value Used: { _timeout } ") ;
128136 _nss ??= new nitro_service ( _clientMachine , _useSsl ? "https" : "http" ) ;
137+ _nss . set_timeout ( _timeout ) ;
138+
129139 base_response response = null ;
130140 try
131141 {
132- response = _nss . login ( _username , _password , Timeout ) ;
142+ response = _nss . login ( _username , _password , _timeout ) ;
133143 Logger . LogDebug ( $ "Login Response: { JsonConvert . SerializeObject ( response ) } ") ;
134144 }
135145 catch ( Exception ex )
@@ -287,7 +297,7 @@ public string FindKeyPairByCertPath(string certPath)
287297 }
288298 }
289299
290- public void UpdateKeyPair ( string keyPairName , string certFileName , string keyFileName )
300+ public void UpdateKeyPair ( string keyPairName , string certFileName , string keyFileName , string keyPassword )
291301 {
292302 Logger . MethodEntry ( LogLevel . Debug ) ;
293303
@@ -302,8 +312,8 @@ public void UpdateKeyPair(string keyPairName, string certFileName, string keyFil
302312 key = keyFileName ,
303313 inform = "PEM" ,
304314 nodomaincheck = true ,
305- passplain = "0" ,
306- password = false
315+ passplain = keyPassword ,
316+ password = keyPassword == null ? null : false
307317 } ;
308318
309319 var filters = new filtervalue [ 1 ] ;
@@ -328,8 +338,9 @@ public void UpdateKeyPair(string keyPairName, string certFileName, string keyFil
328338 }
329339 catch ( nitro_exception ne )
330340 {
331- Logger . LogError ( $ "Exception occured while trying to add or update { keyPairName } . { LogHandler . FlattenException ( ne ) } ") ;
332- throw ;
341+ string error = $ "Exception occured while trying to add or update { keyPairName } .";
342+ Logger . LogError ( error + LogHandler . FlattenException ( ne ) ) ;
343+ throw new Exception ( error , ne ) ;
333344 }
334345
335346 Logger . MethodExit ( LogLevel . Debug ) ;
@@ -478,47 +489,33 @@ public void LinkToIssuer(string cert, string privateKeyPassword, string keyPairN
478489 Logger . MethodExit ( LogLevel . Debug ) ;
479490 }
480491
481- private ( string , string ) GetPemFromPfx ( byte [ ] pfxBytes , char [ ] pfxPassword )
492+ private ( string , string ) GetPemFromPfx ( byte [ ] pfxBytes , char [ ] pfxPassword , string storePassword )
482493 {
483494 Logger . MethodEntry ( LogLevel . Debug ) ;
484495
485496 try
486497 {
487- var p = new Pkcs12Store ( new MemoryStream ( pfxBytes ) , pfxPassword ) ;
498+ Pkcs12StoreBuilder storeBuilder = new Pkcs12StoreBuilder ( ) ;
499+ Pkcs12Store store = storeBuilder . Build ( ) ;
500+ store . Load ( new MemoryStream ( pfxBytes ) , pfxPassword ) ;
488501
489- // Extract private key
490- var memoryStream = new MemoryStream ( ) ;
491- TextWriter streamWriter = new StreamWriter ( memoryStream ) ;
492- var pemWriter = new PemWriter ( streamWriter ) ;
502+ var alias = store . Aliases . Cast < string > ( ) . SingleOrDefault ( p => store . IsKeyEntry ( p ) ) ;
493503
494- var alias = p . Aliases . Cast < string > ( ) . SingleOrDefault ( a => p . IsKeyEntry ( a ) ) ;
495- Logger . LogTrace ( $ "alias: { alias } " ) ;
504+ X509CertificateEntry [ ] chainEntries = store . GetCertificateChain ( alias ) ;
505+ Org . BouncyCastle . X509 . X509Certificate endCertificate = chainEntries [ 0 ] . Certificate ;
496506
497- var publicKey = p . GetCertificate ( alias ) . Certificate . GetPublicKey ( ) ;
498- if ( p . GetKey ( alias ) == null ) throw new Exception ( $ "Unable to get the key for alias: { alias } ") ;
499- var privateKey = p . GetKey ( alias ) . Key ;
500- var keyPair = new AsymmetricCipherKeyPair ( publicKey , privateKey ) ;
507+ AsymmetricKeyParameter privateKey = store . GetKey ( alias ) . Key ;
508+ PrivateKeyConverter keyConverter = PrivateKeyConverterFactory . FromBCPrivateKeyAndCert ( privateKey , endCertificate ) ;
501509
502- pemWriter . WriteObject ( keyPair . Private ) ;
503- streamWriter . Flush ( ) ;
504- var privateKeyString = Encoding . ASCII . GetString ( memoryStream . GetBuffer ( ) ) . Trim ( ) . Replace ( "\r " , "" )
505- . Replace ( "\0 " , "" ) ;
506- memoryStream . Close ( ) ;
507- streamWriter . Close ( ) ;
510+ string pemString = CryptographicObjectFormatter . PEM . Format ( endCertificate , false ) ;
511+ string keyString = string . Empty ;
508512
509- // Extract server certificate
510- var certStart = "-----BEGIN CERTIFICATE-----\n " ;
511- var certEnd = "\n -----END CERTIFICATE-----" ;
512-
513- string Pemify ( string ss )
514- {
515- return ss . Length <= 64 ? ss : ss . Substring ( 0 , 64 ) + "\n " + Pemify ( ss . Substring ( 64 ) ) ;
516- }
513+ if ( string . IsNullOrEmpty ( storePassword ) )
514+ keyString = PemUtilities . DERToPEM ( keyConverter . ToPkcs8BlobUnencrypted ( ) , Keyfactor . PKI . PEM . PemUtilities . PemObjectType . PrivateKey ) ;
515+ else
516+ keyString = CryptographicObjectFormatter . PEM . Format ( keyConverter , storePassword ) ;
517517
518- var certPem =
519- certStart + Pemify ( Convert . ToBase64String ( p . GetCertificate ( alias ) . Certificate . GetEncoded ( ) ) ) +
520- certEnd ;
521- return ( certPem , privateKeyString ) ;
518+ return ( pemString , keyString ) ;
522519 }
523520 catch ( Exception e )
524521 {
@@ -611,14 +608,14 @@ private systemfile GetSystemFile(string fileName)
611608 }
612609 }
613610
614- public ( systemfile pemFile , systemfile privateKeyFile ) UploadCertificate ( string contents , string pwd ,
611+ public ( systemfile pemFile , systemfile privateKeyFile ) UploadCertificate ( string contents , string certTempPassword , string storePassword ,
615612 string alias , bool overwrite )
616613 {
617614 Logger . MethodEntry ( LogLevel . Debug ) ;
618615
619616 try
620617 {
621- var ( certificate , privateKey ) = GetPemFromPfx ( Convert . FromBase64String ( contents ) , pwd . ToCharArray ( ) ) ;
618+ var ( certificate , privateKey ) = GetPemFromPfx ( Convert . FromBase64String ( contents ) , certTempPassword . ToCharArray ( ) , storePassword ) ;
622619
623620 //upload certificate and key
624621 systemfile certificateFile = UploadFile ( alias , certificate , true , 0 ) ;
@@ -637,6 +634,15 @@ private systemfile GetSystemFile(string fileName)
637634 }
638635 }
639636
637+ private void SetTimeout ( dynamic properties )
638+ {
639+ if ( ! UInt32 . TryParse ( ( properties . timeout == null || string . IsNullOrEmpty ( properties . timeout . Value ) ? DefaultTimeout : properties . timeout . Value ) , out _timeout ) )
640+ {
641+ Logger . LogWarning ( $ "Invalid Custom Field 'timeout' value { properties . timeout . Value } . Value must be an integer. Will use default value of { DefaultTimeout . ToString ( ) } ") ;
642+ _timeout = Convert . ToUInt32 ( DefaultTimeout ) ;
643+ }
644+ }
645+
640646 private systemfile UploadFile ( string alias , string contents , bool isCertificate , int fileNameSuffix )
641647 {
642648 Logger . LogDebug ( "Entering UploadFile() Method..." ) ;
0 commit comments