Skip to content

Commit

Permalink
Merge pull request #70 from CyberSource/security-fixes
Browse files Browse the repository at this point in the history
Security fixes
  • Loading branch information
gnongsie authored Jul 23, 2024
2 parents 25a1952 + d503fd1 commit 94c782a
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 30 deletions.
2 changes: 1 addition & 1 deletion CyberSource.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package >
<metadata>
<id>CyberSource</id>
<version>1.4.6</version>
<version>1.4.7</version>
<title>CyberSource Corporation</title>
<authors>CyberSource Corporation</authors>
<owners>CyberSource Corporation</owners>
Expand Down
4 changes: 2 additions & 2 deletions CyberSource/Base/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.4.6")]
[assembly: AssemblyFileVersion("1.4.6")]
[assembly: AssemblyVersion("1.4.7")]
[assembly: AssemblyFileVersion("1.4.7")]
34 changes: 29 additions & 5 deletions CyberSource/Client/BaseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
using System.ServiceModel.Channels;
using System.ServiceModel.Security.Tokens;
using System.Security.Cryptography.X509Certificates;
using System.Collections.Concurrent;
using System.Collections.Concurrent;
using System.Security;

namespace CyberSource.Clients
{
Expand Down Expand Up @@ -70,15 +71,22 @@ string proxyUser
= AppSettings.GetSetting(null, PROXY_USER);
if (proxyUser != null)
{
string proxyPassword
= AppSettings.GetSetting(null, PROXY_PASSWORD);
SecureString proxyPassword = new SecureString();

foreach (char c in AppSettings.GetSetting(null, PROXY_PASSWORD))
{
proxyPassword.AppendChar(c);
}

proxyPassword.MakeReadOnly();

NetworkCredential credential
= new NetworkCredential(proxyUser, proxyPassword);

CredentialCache cache = new CredentialCache();
cache.Add(new Uri(proxyURL), BASIC_AUTH, credential);
mProxy.Credentials = cache;
proxyPassword.Dispose();
}
}
}
Expand Down Expand Up @@ -201,8 +209,8 @@ int boolVal
merchantID, Configuration.KEY_ALIAS);

config.Password
= AppSettings.GetSetting(
merchantID, Configuration.PASSWORD);
= convertToSecureString(AppSettings.GetSetting(
merchantID, Configuration.PASSWORD));

config.LogFilename
= AppSettings.GetSetting(
Expand Down Expand Up @@ -422,6 +430,22 @@ public static bool IsMerchantCertExpired(Logger logger, string merchantId, DateT

}
return false;
}

private static SecureString convertToSecureString(string originalString)
{
if (originalString == null)
{
return null;
}

var secureString = new SecureString();

foreach (char c in originalString)
secureString.AppendChar(c);

secureString.MakeReadOnly();
return secureString;
}
}
}
25 changes: 21 additions & 4 deletions CyberSource/Client/Configuration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Security;

namespace CyberSource.Clients
{
Expand Down Expand Up @@ -65,7 +66,7 @@ public class Configuration
private string serverURL = null;
private string keyFilename = null;
private string keyAlias = null;
private string password = null;
private SecureString password = null;
private string logFilename = null;
private int logMaximumSize = -1;
private int timeout = -1;
Expand Down Expand Up @@ -195,7 +196,7 @@ public string KeyAlias
/// This is optional. When not set, the value of MerchantID is
/// used.
/// </summary>
public string Password
public SecureString Password
{
get { return password; }
set { password = value; }
Expand Down Expand Up @@ -409,14 +410,30 @@ internal string EffectiveKeyFilename
/// Returns the password that will take effect given
/// the current state of this Configuration object.
/// </summary>
internal string EffectivePassword
internal SecureString EffectivePassword
{
get
{
return( password != null ? password : merchantID);
return( password != null ? password : convertToSecureString(merchantID));
}
}

private SecureString convertToSecureString(string originalString)
{
if (originalString == null)
{
return null;
}

var secureString = new SecureString();

foreach (char c in originalString)
secureString.AppendChar(c);

secureString.MakeReadOnly();
return secureString;
}

/// <summary>
/// Returns the merchantID. Throws an exception when it is null.
/// </summary>
Expand Down
16 changes: 10 additions & 6 deletions CyberSource/Client/NVPClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,12 @@ public static Hashtable RunTransaction(
if (logger != null)
{
logger.LogInfo("Loading certificate for " + config.KeyAlias);
}
X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
}

X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Add(userCertificate);

X509Certificate2 newMerchantCert = null;
X509Certificate2 newCybsCert = null;
Expand Down Expand Up @@ -121,9 +124,10 @@ public static Hashtable RunTransaction(
}
else
{
// Changes for SHA2 certificates support
X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Add(userCertificate);

foreach (X509Certificate2 cert1 in collection)
{
Expand Down
4 changes: 2 additions & 2 deletions CyberSource/Client/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.4.6")]
[assembly: AssemblyFileVersion("1.4.6")]
[assembly: AssemblyVersion("1.4.7")]
[assembly: AssemblyFileVersion("1.4.7")]
Original file line number Diff line number Diff line change
Expand Up @@ -47985,7 +47985,7 @@ public partial class PayerAuthEnrollService : object, System.ComponentModel.INot

private string loginIDField;

private string passwordField;
private System.Security.SecureString passwordField;

private string merchantIDField;

Expand Down Expand Up @@ -48227,10 +48227,11 @@ public string loginID {
[System.Xml.Serialization.XmlElementAttribute(Order=9)]
public string password {
get {
return this.passwordField;
return ConvertToUnsecureString(this.passwordField);
}
set {
this.passwordField = value;
this.passwordField = new System.Net.NetworkCredential(string.Empty, value).SecurePassword;
this.passwordField.MakeReadOnly();
this.RaisePropertyChanged("password");
}
}
Expand Down Expand Up @@ -49011,6 +49012,25 @@ protected void RaisePropertyChanged(string propertyName) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}

public static string ConvertToUnsecureString(System.Security.SecureString secureString)
{
if (secureString == null)
{
return string.Empty;
}

System.IntPtr unmanagedString = System.IntPtr.Zero;
try
{
unmanagedString = System.Runtime.InteropServices.Marshal.SecureStringToGlobalAllocUnicode(secureString);
return System.Runtime.InteropServices.Marshal.PtrToStringUni(unmanagedString);
}
finally
{
System.Runtime.InteropServices.Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
}

/// <remarks/>
Expand Down
10 changes: 7 additions & 3 deletions CyberSource/Client/SoapClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public static ReplyMessage RunTransaction(
X509Certificate2 merchantCert = null;
X509Certificate2 cybsCert = null;
DateTime dateFile = File.GetLastWriteTime(keyFilePath);

if (config.CertificateCacheEnabled)
{
if (!merchantIdentities.ContainsKey(config.KeyAlias) || IsMerchantCertExpired(logger, config.KeyAlias, dateFile, merchantIdentities))
Expand All @@ -90,8 +91,10 @@ public static ReplyMessage RunTransaction(
logger.LogInfo("Loading certificate for " + config.KeyAlias);
}

X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
collection.Add(userCertificate);

X509Certificate2 newMerchantCert = null;
X509Certificate2 newCybsCert = null;
Expand Down Expand Up @@ -124,9 +127,10 @@ public static ReplyMessage RunTransaction(
}
else
{
// Changes for SHA2 certificates support
X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
collection.Add(userCertificate);

foreach (X509Certificate2 cert1 in collection)
{
Expand Down
9 changes: 7 additions & 2 deletions CyberSource/Client/XmlClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,10 @@ public static XmlDocument RunTransaction(
logger.LogInfo("Loading certificate for "+ config.KeyAlias);
}

X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
collection.Add(userCertificate);

X509Certificate2 newMerchantCert = null;
X509Certificate2 newCybsCert = null;
Expand Down Expand Up @@ -140,8 +142,11 @@ public static XmlDocument RunTransaction(
}
else
{
X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
collection.Add(userCertificate);

foreach (X509Certificate2 cert1 in collection)
{
if (cert1.Subject.Contains(config.KeyAlias))
Expand Down
2 changes: 0 additions & 2 deletions CyberSourceSamples/src/soap/SoapSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using CyberSource.Clients;
using CyberSource.Clients.SoapServiceReference;
using System.Security.Cryptography;
//using SoapSampleTransactions;


namespace CyberSource.Samples
Expand Down Expand Up @@ -845,7 +844,6 @@ public RequestMessage saleRequest()
// you would set a merchantID in each request.

// this sample requests auth and capture

// Credit Card Authorization
request.ccAuthService = new CCAuthService();
request.ccAuthService.run = "true";
Expand Down

0 comments on commit 94c782a

Please sign in to comment.