I have below mentioned code:
string urlEncodedData = URL.Text;
byte[] encryptedData = HttpServerUtility.UrlTokenDecode(urlEncodedData);
Type machineKeySection = typeof(System.Web.Configuration.MachineKeySection);
Type[] paramTypes = new Type[] { typeof(bool), typeof(byte[]), typeof(byte[]), typeof(int), typeof(int) };
MethodInfo encryptOrDecryptData = machineKeySection.GetMethod("EncryptOrDecryptData", BindingFlags.Static | BindingFlags.NonPublic, null, paramTypes, null);
try
{
byte[] decryptedData = (byte[])encryptOrDecryptData.Invoke(null, new object[] { false, encryptedData, null, 0, encryptedData.Length });
string decrypted = Encoding.UTF8.GetString(decryptedData);
decryptedLabel.BackColor = Color.Lime;
decryptedLabel.Text = decrypted;
}
catch (TargetInvocationException)
{
decryptedLabel.BackColor = Color.Red;
decryptedLabel.Text = "Error decrypting data. Are you running your page on the same server and inside the same application as the web resource URL that was generated?";
}
It Decrypts and tell me details about webresource.
locally it works fine.
But on production it always gives me below message from catch block
Error decrypting data. Are you running your page on the same server and inside the same application as the web resource URL that was generated?
The only difference I have is production being on HTTPS. Is above code valid for HTTPS also, or do I have to make change(s) to it?
I also was using this code snippet to decrypt webresource.axd parameter, but lately it stopped working.
Maybe it's change of framework to 4.5, because I found this comment in .net sources - Page class, method DecryptString http://referencesource.microsoft.com/#System.Web/UI/Page.cs,18cf7b1fe99faea6
if (AspNetCryptoServiceProvider.Instance.IsDefaultProvider) {
// ASP.NET 4.5 Crypto DCR: Go through the new AspNetCryptoServiceProvider
// if we're configured to do so.
ICryptoService cryptoService = AspNetCryptoServiceProvider.Instance.GetCryptoService(purpose, CryptoServiceOptions.CacheableOutput);
clearData = cryptoService.Unprotect(protectedData);
}
else {
// If we're not configured to go through the new crypto routines,
// fall back to the standard MachineKey crypto routines.
#pragma warning disable 618 // calling obsolete methods
clearData = MachineKeySection.EncryptOrDecryptData(fEncrypt: false, buf: protectedData, modifier: null, start: 0, length: protectedData.Length, useValidationSymAlgo: false, useLegacyMode: false, ivType: IVType.Hash);
#pragma warning restore 618 // calling obsolete methods
}
Are you sure the only difference is http and https, maybe framework version also?
Nevertheless I used method DecryptString instead EncryptOrDecryptData and below code is working for me. You can check if this working for you too :)
private static string Decrypt(string webResourceParameter)
{
var purposeType = Type.GetType("System.Web.Security.Cryptography.Purpose, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
if (purposeType == null)
return null;
try
{
var purpose = Activator.CreateInstance(purposeType, "AssemblyResourceLoader.WebResourceUrl");
const BindingFlags decryptFlags = BindingFlags.NonPublic | BindingFlags.Static;
var decryptString = typeof (Page).GetMethod("DecryptString", decryptFlags);
var decrypt = decryptString.Invoke(null, new[] {webResourceParameter, purpose}) as string;
return decrypt;
}
catch (Exception ex)
{
return null;
}
}
Related
I've searched long and hard for a solution to this, unfortunately nothing I've tried so far has worked.
Question: how do I set the logon credentials for the service this function is installing? At the moment it defaults to localsystemaccount.
When I try to add in an event handler to set the account and password for logon as per the example seen here:
https://csharp.hotexamples.com/site/file?hash=0xf9962fd5be4a761736a9d350fdd72135dd0954853d267eca8ccbd9349e15f467&fullName=VirtualBoxService/ElevatedService.cs&project=shabbirh/virtualboxservice
I get an error:
Type 'System.Configuration.Install.InstallerCollection' in assembly 'System.Configuration.Install, version 4.0.0.0,.... .... is not marked as serializable"
private bool TryInstallWindowsService(WindowsService WinService)
{
IDictionary mySavedState = new Hashtable();
var domain = AppDomain.CreateDomain("MyDomain");
// Create an object of the 'AssemblyInstaller' class.
using (AssemblyInstaller Installer = domain.CreateInstance(typeof(AssemblyInstaller).Assembly.FullName,
typeof(AssemblyInstaller).FullName, false, BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.ExactBinding,
null, new Object[] { WinService.DefaultPath, new String[] { } }, null, null, null).Unwrap() as AssemblyInstaller)
{
Installer.UseNewContext = true;
//The below line causes an error to be thrown "Type 'System.Configuration.Install.InstallerCollection' in assembly 'System.Configuration.Install, version 4.0.0.0,....
//.... is not marked as serializable"
//Installer.BeforeInstall += new InstallEventHandler(installer_BeforeInstall);
try
{
// Install the 'MyAssembly' assembly.
myAssemblyInstaller.Install(mySavedState);
// Commit the 'MyAssembly' assembly.
myAssemblyInstaller.Commit(mySavedState);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
myAssemblyInstaller.Rollback(mySavedState);
return false;
}
finally
{
myAssemblyInstaller.Dispose();
}
}
AppDomain.Unload(domain);
return true;
}
I am getting the xml, signature and signature-algoirthm seperate in a http-get.
so, How do I approach this to validate the signature?
currently my code is this:
public void CheckSignature(string response, string sig, string sigalg, byte[] cert)
{
Log("loading cert");
X509Certificate2 cert2 = new X509Certificate2(cert);
bool result = false;
/* response, sigalg and sig are url-decoded or not, doesn't matter :( */
Log("first variant");
var signedString = string.Format(CultureInfo.InvariantCulture, "SAMLResponse={0}&SigAlg={1}", response, sigalg);
result = DoCheck(signedString, sigalg, sig, cert2);
Log("2nd variant");
signedString = string.Format(CultureInfo.InvariantCulture, "SAMLResponse={0}", response);
result = DoCheck(signedString, sigalg, sig, cert2);
Log("3rd variant");
signedString = string.Format(CultureInfo.InvariantCulture, "{0}", response);
result = DoCheck(signedString, sigalg, sig, cert2);
}
private bool DoCheck(string signedString, string sigalg, string sig, X509Certificate2 cert2)
{
try {
var sigDescription = (SignatureDescription)CryptoConfig.CreateFromName(sigalg);
var hashAlg = sigDescription.CreateDigest();
//why is this needed?
hashAlg.ComputeHash(Encoding.UTF8.GetBytes(signedString));
var signature = Convert.FromBase64String(sig);
Log("trying to verify::" + signedString + Environment.NewLine);
X509AsymmetricSecurityKey key = new X509AsymmetricSecurityKey(cert2);
AsymmetricAlgorithm asym_alg = key.GetAsymmetricAlgorithm(sigalg, false);
AsymmetricSignatureDeformatter def = sigDescription.CreateDeformatter(asym_alg);
bool result = false;
result = def.VerifySignature(hashAlg, signature);
//sadly always false.
Log("woop woop:" + result);
return result;
}
catch (Exception ex) {
Log(ex.Message);
Log(ex.StackTrace);
}
return false;
}
but for now, whatever I do, the result is always false.
based on https://github.com/KentorIT/authservices/blob/master/Kentor.AuthServices/WebSSO/Saml2RedirectBinding.cs
If you get a query string on the form SAMLResponse=....SigAlg=...Signature=... (first param can also be SAMLRequest) you are getting a message using the SAML2 HTTP Redirect binding. Please see the SAML2 Specification for a description of how it works. Specifically you should read the binding specification.
Or if you want to save yourself a lot of work, find an existing SAML2 implementation to use instead. There are several open source implementations for C# available.
Well,
I found it out myself.
It really is the issue of the rawrequest parameters.
(My code already parsed it, but then it fails anyhow)
// Can't use the query string params as found in HttpReqeustData
// because they are already unescaped and we need the exact format
// of the original data.
var rawQueryStringParams = request.Url.Query.TrimStart('?')
.Split('&')
.Select(qp => qp.Split('='))
.ToDictionary(kv => kv[0], kv => kv[1]);
https://msdn.microsoft.com/en-us/library/system.uri(v=vs.110).aspx
According to the reference above, when specifying an ftp url, the uri class should not compact the url. For example, the following ftp url:
Uri uri = new Uri("ftp://myUrl/%2E%2E/%2E%2E");
Console.WriteLine(uri.AbsoluteUri);
Console.WriteLine(uri.PathAndQuery);
should result in:
AbsoluteUri: "ftp://myUrl/%2E%2E/%2E%2E"
PathAndQuery: "/%2E%2E/%2E%2E"
But, this is NOT what I'm seeing. When I execute the above code using .NET framework 4.5.1, I see:
AbsoluteUri: "ftp://myUrl/"
PathAndQuery: "/"
Moreover, adding to my app.config seems to have no effect:
<uri>
<schemeSettings>
<add name="ftp" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
Since several people have been able to recreate the issue, I've created a bug report with Microsoft. Feel free to upvote:
https://connect.microsoft.com/VisualStudio/feedback/details/2046491/uri-canonicalization-compacting-ftp-scheme
Created a bug report with Microsoft:
https://connect.microsoft.com/VisualStudio/Feedback/Details/2046491
At present, I am working around this issue by (hacking via reflection) removing two flags from the UriParser object within the Uri class:
I call the method below once when my application is instantiating. After instantiation, every FTP Uri object will utilize the new flag combination when parsing.
// CompressPath = 0x800000, // For an authority based Uri remove/compress /./ /../ in the path
// UnEscapeDotsAndSlashes = 0x2000000, // additionally unescape dots and slashes before doing path compression
/// <summary>
/// http://referencesource.microsoft.com/#System/net/System/_UriSyntax.cs
/// </summary>
public static void LeaveDotsAndSlashesEscaped() {
Uri uri = new Uri("ftp://myUrl/%2E%2E/%2E%2E/");
if (uri == null) {
throw new ArgumentNullException("uri");
}
FieldInfo fieldInfo = uri.GetType().GetField("m_Syntax", BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo == null) {
throw new MissingFieldException("'m_Syntax' field not found");
}
object uriParser = fieldInfo.GetValue(uri);
fieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo == null) {
throw new MissingFieldException("'m_Flags' field not found");
}
object uriSyntaxFlags = fieldInfo.GetValue(uriParser);
// Clear the flags that we don't want
uriSyntaxFlags = (int)uriSyntaxFlags & ~0x2000000 & ~0x800000;
fieldInfo.SetValue(uriParser, uriSyntaxFlags);
}
So, the below code used to work in .NET 4 to get a System.Net.Mail.MailMessage object as a MemoryStream, however with the release of .NET 4.5 beta a runtime exception occurs.
Assembly assembly = typeof(SmtpClient).Assembly;
Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
using (MemoryStream stream = new MemoryStream())
{
ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
object mailWriter = mailWriterContructor.Invoke(new object[] { stream });
MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true }, null);
.....
}
Runtime exception occurs on sendMethod.Invoke().
Managed to figure out how to get this working again in .NET 4.5 beta. The private API Send() method in MailMessage has changed to: internal void Send(BaseWriter writer, bool sendEnvelope, bool allowUnicode)
Please find updated code below.
Assembly assembly = typeof(SmtpClient).Assembly;
Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
using (MemoryStream stream = new MemoryStream())
{
ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
object mailWriter = mailWriterContructor.Invoke(new object[] { stream });
MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true, true }, null);
.....
}
This might be usable if you don't want to go with unsupported hacks and don't mind extra performance hit.
public static class MailMessageExtensions
{
public static string RawMessage(this MailMessage m)
{
var smtpClient = new SmtpClient { DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory };
using (var tempDir = new TemporaryDirectory())
{
smtpClient.PickupDirectoryLocation = tempDir.DirectoryPath;
smtpClient.Send( m );
var emlFile = Directory.GetFiles( smtpClient.PickupDirectoryLocation ).FirstOrDefault();
if ( emlFile != null )
{
return File.ReadAllText( emlFile );
}
else
return null;
}
return null;
}
}
class TemporaryDirectory : IDisposable
{
public TemporaryDirectory()
{
DirectoryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory( DirectoryPath );
}
public string DirectoryPath { get; private set; }
public void Dispose()
{
if ( Directory.Exists( DirectoryPath ) )
Directory.Delete( DirectoryPath, true );
}
}
for checking if extra boolean i use :
If _sendMethod.GetParameters.Length = 2 Then
_sendMethod.Invoke(Message, BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, New Object() {_mailWriter, True}, Nothing)
Else
_sendMethod.Invoke(Message, BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, New Object() {_mailWriter, True, True}, Nothing)
End If
The proposed solution with the extra TRUE works beautifully.
I started to getting the error while running my project in VS2012 even though I am not using .net 4.5 but 4.0 in all my libraries.
The error only happens on the machine where you have installed VS2012, looks like VS2012 makes reference to .net 4.5 while you are debugging. When you deploy and run the application in clients running .net 4.0 everything works fine.
Thus : If you run 4.0 - do not add the extra TRUE, if you run 4.5 add it.
We fought with the mail message conversion for a long time. Ultimately the solution was to use MimeKit.
var memoryStream = new MemoryStream();
var mimeMessage = MimeMessage.CreateFromMailMessage(message);
mimeMessage.WriteTo(memoryStream);
If you use the methods above you will get really close and it will work in most cultures but eventually the subject encoding will defeat you.
For those, who are struggling with mailWriterContructor being null in .NET 5 or facing Parameter count mismatch exception, take a closer look on my solution usable for any stream. Link here
I know I should write this in Vb.net but for my own reasons I'm attempting late binding against a Com Object in C# .net framework 3.5. The error I'm getting is "DISP_E_BADCALLEE" and I'm only getting that based on when the copybacks I want are set to true. Am I dealing with a security issue? My research lead me to try dropping "[assembly: AllowPartiallyTrustedCallers()]" in the AssemblyInfo file but that didn't do the trick. I dropped some details in a condensed version of the code below. It's failing on the 4th step. I'd appreciate your help. Thanks.
//step 1
_atlDirectorObject = Activator.CreateInstance(Type.GetTypeFromProgID("atlDirectorObject.atlDirector"));
//step 2
object[] parms = { "3270", 1, true, true, 0, _atl3270Tool, _ErrMsg };
Boolean[] CopyBack2 = new Boolean[7];
CopyBack2[5] = true; //atl3270Tool
CopyBack2[6] = true; //ErrMsg
Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateCall(_atlDirectorObject, _atlDirectorObject.GetType(), "CreateTool", parms, null, null, CopyBack2, false);
_atl3270Tool = parms[5];
//step 3
// now using _atl3270Tool we navigate mainframe screens
object[] parms3 = { Screen, SubScreen, _Number, _ErrMsg };
Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateCall(_atl3270Tool, _atl3270Tool.GetType(), "ShowScreen", parms3, null, null, null, false);
//>>>>>>>>>>>>>>CODE FAILS ON THIS STEP<<<<<<<<<<<<
//step 4
Boolean[] CopyBack4 = new Boolean[5];
CopyBack4[3] = true; //screentext
CopyBack4[4] = true; //_errmsg
object ScreenText = String.Empty;
object[] parms4 = { Row, Col, Length, ScreenText, _ErrMsg};
Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateCall(_atl3270Tool, _atl3270Tool.GetType(), "ReadScreen", parms4, null, null, CopyBack4, false)
// if it were working the code would read screen data into parms4[3] object
// If CopyBack4[3 and/or 4] are set to true = error
// Is just CopyBack4[0,1,2] are true = no error but no result
//Errors out with "Invalid callee. (Exception from HRESULT: 0x80020010 (DISP_E_BADCALLEE))"
return Convert.ToString(parms4[3]);
ScreenText should be set to null, not string.empty