I'm new to sftp and i'm trying to get a c# program to send a file via sftp to a remote server not under my control.
Using code like:
using (var sftp = new SftpClient(FTPAddress, FTPName, FTPPassword))
{
ConnectionInfo myCI = sftp.ConnectionInfo;
sftp.Connect(); // <<<< Exception on connect
sftp.UploadFile(sftp_ms, FileName,true);
sftp.Disconnect();
}
I receive a "Bad packet length" exception.
Google searching reveals that a bad packet length is likely to be a mismatch in encryption formats but I don't know how to resolve that.
The specification i've received from the client is:
Keys must be in Open SSH version 2 format RSA format
I don't know how to do this. A previous SO question How to resolve a 'Bad packet length' error in SSH.NET? has a link to sshnet.codeplex discussion where removing the encryption keys that you don't want solved the issue for that poster.
I can see 16 entries in ssh.net's connectioninfo class but none of them state open SSH version 2 RSA though one of them may very well be (i've tried googling).
I have tried the ip, name and password i've been given with filezilla and I connect no problems; so filezilla somehow uses the correct encryption; I don't know how to tell what it's using.
Help ?
Andrew
You've got two different problems here. If you're getting the bad packet length problem, then you probably have to follow the guide in the ssh.net Codeplex discussion to resolve the negotiation. This should resolve the establishing of the initial connection.
If you're required to use an ssh private key for connection, then you have to use one of the constructors that takes an array of PrivateKey objects. One of the constructors for a PrivateKey takes a stream, and you can convert the private key string to the stream using code like:
var privKey = new PrivateKey(new MemoryStream(Encoding.ASCII.getBytes(sshPrivateKeyString)));
var sftpclient = new SftpClient(FTPAddress, FTPName, new PrivateKeyFile[] { privKey });
Other mechanisms are to use an explicit PrivateKeyConnectionInfo instance:
var privKey = new PrivateKey(new MemoryStream(Encoding.ASCII.getBytes(sshPrivateKeyString)));
var privConnInfo = new PrivateKeyConnectionInfo(FTPAddress, FTPName, privKey);
var sftpClient = new SftpClient(privConnInfo);
Related
How to run Verify the existence of a mailbox address.?
http://www.mimekit.net/docs/html/M_MailKit_Net_Smtp_SmtpClient_Verify.htm
using (var client = new SmtpClient())
{
client.Connect("smtp.mail.ru", 465, true);
client.Authenticate(name, pass);
var d = client.Verify(email);
}
Error MailKit.Net.Smtp.SmtpCommandException: "unrecognized command"
Most SMTP servers do not support the VRFY command anymore. Your server doesn't support it which is why you are getting an error.
Possible a duplicate.
You can read this question, it's in PHP but all the concepts are the same for your situation.
As jstedfast said, that command isn't supported anymore and to sum up your reading: There is not a reliable way to verify that anymore because of spams.
Below Code is just working fine with IBMMQ 8.0 DLL and server when I switch to 7.5 (both DLL and server) it is giving me this error using same certificate
The SSL key repository cannot be used because MQ cannot obtain a
password to access it. Reasons giving rise to this error include: &B
(a) the key database file and password stash file are not present in
the location configured for the key repository, &B (b) the key
database file exists in the correct place but that no password stash
file has been created for it, &B (c) the files are present in the
correct place but the userid under
public void test() {
Environment.SetEnvironmentVariable("MQCCSID", "437");
MQQueueManager mQQueueManager = null;
MQQueue mQQueue = null;
Hashtable hashTable = null;
try {
hashTable = new Hashtable();
// Setup properties for connection
hashTable.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
hashTable.Add(MQC.HOST_NAME_PROPERTY, "IP");
hashTable.Add(MQC.PORT_PROPERTY, 1414);
hashTable.Add(MQC.CHANNEL_PROPERTY, "Channel");
hashTable.Add(MQC.PASSWORD_PROPERTY, "123");
hashTable.Add(MQC.USER_ID_PROPERTY, "user");
mQQueueManager = new MQQueueManager("QueueName", hashTable);
// Open queue for browsing
mQQueue = mQQueueManager.AccessQueue("que", MQC.MQOO_BROWSE | MQC.MQOO_FAIL_IF_QUIESCING);
ListOfMessages = new List < MQMessageDto > ();
// In a loop browse all messages till we reach end of queue
while (true) {
try {
// Need to create objects everytime
var mQMessage = new MQMessage();
var mQGetMessageOptions = new MQGetMessageOptions {
// Use browse next option to start browsing
Options = MQC.MQGMO_BROWSE_NEXT
};
mQQueue.Get(mQMessage, mQGetMessageOptions);
ListOfMessages.Add(new MQMessageDto() {
Id = ListOfMessages.Count + 1,
Message = Encoding.UTF8.GetString(mQMessage.ReadBytes(mQMessage.MessageLength))
});
} catch (MQException mqex) {
if (ListOfMessages.Count == 0) {
MessageBox.Show("There is no messages in MQ");
}
mQQueue.Close();
break;
}
}
mQQueueManager.Disconnect();
grdMessages.DataSource = ListOfMessages;
grdMessages.Columns["Id"].Width = (int)(grdMessages.Width * 0.1);
grdMessages.Columns["Message"].Width = (int)(grdMessages.Width * 0.8);
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
What are you describing means you have wrong configuration at IBM side, and Since you are using IBM MQ 7.5. I think you got the path for the SSL key repository wrong, it should point to the key name not the folder.
Also make sure that you have selected Optional from SSL tab inside your Channel.
For more details.. More details about this issue can be found here about error this error code:
2538 error on MQ for SSL channel connection
You didn't mention which specific level of 7.5 you are using. If it is 7.5.0.7 or earlier, the stash file will likely be the problem:
https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.mig.doc/q128820_.htm
Older versions of the cryptographic provider used by MQ (GSKit) use a different stash file format for the keystore password.
While newer GSKit versions can handle the old stash file format, the new format is not readable by older GSKit versions. If you are using a level which uses the new format, you can create a backwards-compatible stash file with the -v1stash option:
runmqakm -keydb -stashpw -db <filename> -pw <password> -v1stash
A better alternative, as MQ 7.5 is out of support, would be to use a newer client level, which can still communicate with a 7.5 queue manager if required.
For reference, the first GSKit level which uses the new stash file format is 8.0.50.69. Levels of GSKit bundled with MQ are listed here: https://www.ibm.com/support/pages/levels-jre-and-gskit-bundled-ibm-mq
Regarding:
When I upgraded my client to V9 I'm getting "MQRC_Q_MGR_NOT_AVAILABLE" on client and "4/23/2020 21:03:22 - Process(11764.64) User() Program(amqrmppa.exe) Host(HOST) Installation(Installation1) VRMF(7.5.0.2) QMgr() Remote channel '' did not specify a CipherSpec. Remote channel '' did not specify a CipherSpec when the local channel expected one to be specified. &P The remote host is '...* (...)'. &P The channel did not start. Change the remote channel '' on host ()' to specify a CipherSpec so that both ends of the channel have matching CipherSpecs." in server
display the cipher spec being used dis chl(xxx) SSLCIPH
You may have specified something which is no longer supported by the underlying TLS support.
dis chl(xxx)
I am trying to push a message to IBM MQ but while adding properties like HostName, channel and Port I am getting below error when I continue the debug without stopping
Item has already been added. Key in dictionary: 'Hostname' Key being added: 'Hostname' in c#.
I have tried to validate as below,
if (!MQEnvironment.properties.ContainsKey(strHost) && !MQEnvironment.properties.ContainsKey(intPort) && !MQEnvironment.properties.ContainsKey(strChannel))
{
MQEnvironment.properties.Add("Hostname", strHost);
MQEnvironment.properties.Add("Port", intPort);
MQEnvironment.properties.Add("Channel", strChannel);
MQEnvironment.properties.Add(MQC.TRANSPORT_PROPERTY,MQC.TRANSPORT_MQSERIES);
}
above code contains in my MQ PutMessage method where I am pushing my message.
Yuk (and a headache for future support).
First off, the MQEnvironment class is a static class and should ONLY be used for super simple programs. The IBM MQ best practices is to use a HashTable.
Second, why are you not using the supplied MQ defines for the key names? (it will eliminate typos)
Third, you need to review the MQ Knowledge Center for the correct MQ .NET values for 'TRANSPORT_PROPERTY'. Please see here. There are 4 valid values for MQ .NET:
MQC.TRANSPORT_MQSERIES_BINDINGS - connect as server
MQC.TRANSPORT_MQSERIES_CLIENT - connect as non-XA client
MQC.TRANSPORT_MQSERIES_XACLIENT - connect as XA client
MQC.TRANSPORT_MQSERIES_MANAGED - connect as non-XA managed client
Here is the proper way to code it:
Hashtable qMgrProp = new Hashtable();
qMgrProp.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
qMgrProp.Add(MQC.HOST_NAME_PROPERTY, strHost);
qMgrProp.Add(MQC.PORT_PROPERTY, intPort);
qMgrProp.Add(MQC.CHANNEL_PROPERTY, strChannel);
MQQueueManager qMgr = new MQQueueManager(qMgrName, qMgrProp);
It looks like it's not strHost that's already there, it's "Hostname". You'd need to change your checking to be:
MQEnvironment.properties.ContainsKey("HostName")
etc.
I'm trying to use SSH.NET in C# code to access a database over SSH. I generate a RSA key pair and put the private key on an UNC shared drive. The pathname string looks like below. When I kick off the code trying to connect, I get a "Could not find a part of the path" error.
string privatekeypathname = #"\\server\My path\private_key.ppk";
I think using an UNC path is the issue. Is there any way to resolve the issue? Thanks.
Edit: I tried using a mapped drive. Same error. My Code looks like:
PrivateKeyFile key = new PrivateKeyFile(privatekeypathname, MyPassPhrase);
ConnectionInfo connectionInfo = new ConnectionInfo(
MySSHHost,
MySSHPort,
MySSHUser,
new PrivateKeyAuthenticationMethod(MySSHUser, key));
sshClient = new SshClient(connectionInfo);
sshClient.Connect();
Note: I've tried a pathname that looks like: #"C:\my folder\private_key.ppk" and it works, so obviously the space in the string isn't the issue. Also, although I don't think permission is the issue, I've tried running the code as administrator and got the same error. I can manually access the shared drive using Windows Explorer. I don't know what else I can try to verify this end.
I want to read the contents of a CSR in C#. However, I haven't found any way to do it in C#.
What I've found was the namespace System.Security.Cryptography.X509Certificates, but it only handles existing certificates, not certificate requests.
Can anyone give me an hint about it?
Thanks in advance.
There is a way, the CertEnroll library which comes with Windows (although I can't say how far back it's been there) allows you to load certificate requests and have them parsed.
First you need to import a reference to the CERTENROLLLib COM library into your project. This will create a CERTENROLLLib name space you can then use.
Then you do something like this;
string csr = "-----BEGIN CERTIFICATE REQUEST-----\r\n" +
"MIIBnTCCAQYCAQAwXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIw\r\n" +
"EAYDVQQDEwlsb2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5l\r\n" +
"eGFtcGxlLmRvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr1nYY1Qrll1r\r\n" +
"uB/FqlCRrr5nvupdIN+3wF7q915tvEQoc74bnu6b8IbbGRMhzdzmvQ4SzFfVEAuM\r\n" +
"MuTHeybPq5th7YDrTNizKKxOBnqE2KYuX9X22A1Kh49soJJFg6kPb9MUgiZBiMlv\r\n" +
"tb7K3CHfgw5WagWnLl8Lb+ccvKZZl+8CAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GB\r\n" +
"AHpoRp5YS55CZpy+wdigQEwjL/wSluvo+WjtpvP0YoBMJu4VMKeZi405R7o8oEwi\r\n" +
"PdlrrliKNknFmHKIaCKTLRcU59ScA6ADEIWUzqmUzP5Cs6jrSRo3NKfg1bd09D1K\r\n" +
"9rsQkRc9Urv9mRBIsredGnYECNeRaK5R1yzpOowninXC\r" +
"-----END CERTIFICATE REQUEST-----";
CX509CertificateRequestPkcs10 request = new CX509CertificateRequestPkcs10();
request.InitializeDecode(csr, EncodingType.XCN_CRYPT_STRING_BASE64_ANY);
request.CheckSignature();
Console.WriteLine(((CX500DistinguishedName)request.Subject).Name);
Console.WriteLine(request.PublicKey.Length);
Console.WriteLine(request.HashAlgorithm.FriendlyName);
You can see the only fun part is getting the subject name out, as you need to cast it to a CX500DistinguishedName instance first.
Look at BouncyCastle's C# implementation. Used it for PGP stuff in the past, worked great. Something like this should get you started (not tested):
var textReader = File.OpenText(...);
var reader = new Org.BouncyCastle.OpenSsl.PEMReader(textReader);
var req = reader.ReadObject() as Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest;
var info = req.GetCertificationRequestInfo();
Console.WriteLine(info.Subject);
This is how you do it with OpenSSL.NET library:
// Load the CSR file
var csr = new X509Request(BIO.File("C:/temp/test.csr", "r"));
OR
var csr = new X509Request(#"-----BEGIN CERTIFICATE REQUEST-----...");
// Read CSR file properties
Console.WriteLine(csr.PublicKey.GetRSA().PublicKeyAsPEM);
Console.WriteLine(csr.Subject.SerialNumber);
Console.WriteLine(csr.Subject.Organization);
.
.
.
X509Request type has properties to get everything out of your CSR file text.
It seems to me the best way for you is usage unmanaged CryptoAPI or P/Invoke. CryptoAPI has CERT_REQUEST_INFO data struct and CryptSignAndEncodeCertificate function which can be used with X509_CERT_REQUEST_TO_BE_SIGNED parameter. Of cause theoretically it's possible to encode request manually with respect of AsnEncodedData, because CSR is not complex (see http://en.wikipedia.org/wiki/Certificate_signing_request and http://www.rfc-editor.org/rfc/rfc2311.txt), but I don't think that it has a sense if an implementation already exist in CryptoAPI.
A good examples to create CSR with respect of CryptoAPI you will find in http://msdn.microsoft.com/en-us/library/aa382364(VS.85).aspx and http://msdn.microsoft.com/en-us/library/ms867026.aspx.
To read Certificate Signing request , you can use method LoadSigningRequestPem availaible in class - "System.Security.Cryptography.X509Certificates.CertificateRequest".
using System.Security.Cryptography.X509Certificates;
string csr = #"-----BEGIN CERTIFICATE REQUEST-----
MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNV
BAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGln
aUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmo
wp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c
1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiI
WDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZ
wIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPR
BPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJ
KoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6D
hJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpY
Q4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/
ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn
29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO2
97Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=
-----END CERTIFICATE REQUEST-----";
CertificateRequest certReq = CertificateRequest.LoadSigningRequestPem(csr,HashAlgorithmName.SHA256);
Console.WriteLine("Subject Name: {0}",certReq.SubjectName.Name);
I had the same issue. I didn;t find a solution so "invented" ;) on a work around. CertUtil.exe is microsoft's command line utility to create, read,submit, accept and install certs.
I used System.Diagnostics.Process to create external process and passed the CSR request file as argument to read the file into a stream. Heres the code for it.
using (System.Diagnostics.Process extProc = new System.Diagnostics.Process())
{
extProc.StartInfo.CreateNoWindow = true;
extProc.StartInfo.UseShellExecute = false;
extProc.StartInfo.RedirectStandardOutput = true;
extProc.StartInfo.FileName = #"C:\certtest\Util_xpVersion\certutil.exe";
extProc.StartInfo.Arguments = "-dump \"C:\\certtest\\Util_xpVersion\\ToolCSR.crq\"";
extProc.Start();
extProc.WaitForExit();
string sTemp = extProc.StandardOutput.ReadToEnd();
extProc.Close();
}