I want to connect to a cisco switch via telnet in c#.I want to send commands in cmd with c# and when it asks for password I want to enter it with my program. But my problem is that I can’t send password when it is connected to telnet.And when I used StreamWriter it throws an exception.
Here is my code:
class Program
{
static void Main(string[] args)
{
string data = "";
StreamReader reader = new StreamReader(#"C:\Windows\System32");
StreamWriter writer = new StreamWriter(#"C:\Windows\System32");
IPAddress address = IPAddress.Parse("172.16.0.110");
IPEndPoint ipe = new IPEndPoint(address, 23);
Socket telnetSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
telnetSocket.Connect(ipe);
NetworkStream NsStream = new NetworkStream(telnetSocket, true);
if (telnetSocket.Connected)
{
NsStream = new NetworkStream(telnetSocket, true);
reader = new StreamReader(NsStream);
}
while (!reader.EndOfStream)
{
data = reader.ReadLine();
if (data.Contains("Password:"))
{
//I want to enter password in cmd here
}
}
reader.Close();
if (NsStream == null)
NsStream.Close();
}
}
You're going to need to talk Telnet. Telnet rfcs will give you an idead what you're dealing with. https://www.rfc-editor.org/rfc/rfc854
If you want to hand-roll this, a few suggestions that might help. Or else show why it might be a good idea to use a telnet library.
TcpClient will reduce your work a little. At least it will create the NetworkStream for you.
You can probably ignore much of the protocol details, but not the initial option negotiation. You probably want to deal with the raw NetworkStream initially, because telnet sessions start with 'option' negotiation. A quick search for telnet option negotiation turns this up: How to deal with the telnet negotiation
There are two problems using the reader/writer above:
They will be using UTF8 encoding by default, so the telnet option negotiation data (which isn't 7 bit ASCII) will likely get mutated.
Readline() will probably hang anyway, as it will read the telnet options, which are the first thing sent by the server, but then keeping trying to read until the first end of line ... which will never arrive because the server is waiting for a response to the options it sent. i.e. you need to finish the telnet option negotiation.
If you use a lib like SSH.NET you get all these problems solved for you and no need to reinvent the wheel again!
Related
This is the situation. I have a Windows machine and a Linux machine. There is a shared drive between these two machines (which is mapped to Q:). I am trying to figure out how to create an SSH session at the Q: drive (shared drive) from C#. I am trying to use the SharpSsh library to do this.
This is what I have so far, however, it is giving me an error:
try
{
ssh = new SshStream(host, username, password);
Console.WriteLine("OK ({0}/{1})", ssh.Cipher, ssh.Mac);
Console.WriteLine("Server version={0}, Client version={1}", ssh.ServerVersion, ssh.ClientVersion);
Console.WriteLine("-Use the 'exit' command to disconnect.");
Console.WriteLine();
//Sets the end of response character
ssh.Prompt = "#";
//Remove terminal emulation characters
ssh.RemoveTerminalEmulationCharacters = true;
//Reads the initial response from the SSH stream
Console.Write(ssh.ReadResponse()); // Blocking here
while (true)
{
string command = Console.ReadLine();
if (command.ToLower().Equals("exit"))
break;
//Write command to the SSH stream
ssh.Write(command);
//Read response from the SSH stream
Console.Write(ssh.ReadResponse());
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
if(ssh != null)
{
ssh.Close();
}
I have added the Tamir.SharpSSH.dll as a reference to the project, and I am using it in the project. There are two other dll's that are included with SharpSSH, do I need to add them as well to the references? The examples I have seen only have the Tamir.SharpSSH.dll as a reference.
I am not sure how to initiate the connection in the correct location, and how to submit commands properly to the ssh.
UPDATE
I realized I needed to close the SSH connection before ending the program. The error does not exist anymore, however, I am still not getting any information from my "ls" command.
UPDATE
I updated the code with what I have now. It seems like the ssh.ReadResponse() is blocking, which leads me to believe the server is not responding. Is that correct?
I try to send a code(TLRequestAuthSendCode) but it doesn't come. In what there can be a problem?
Part of code:
TLContext tlContext = new TLApiContext();
TcpClient tcpClient = new TcpClient();
tcpClient.Connect(connections[0].getAddress(), (int)connections[0].getPort());
TLRequestAuthSendCode tlRequestAuthSendCode = new TLRequestAuthSendCode("PHONE_NUMBER",
0, 19114, "TOKEN", "en");
tlRequestAuthSendCode.serializeBody(new StreamWriter(tcpClient.GetStream()));
can you debug your code and tell if
tcpClient.Connect(connections[0].getAddress(),
Connections[0] has a value?
I'd suggest you change your code to the following:
public void run() {
connections = new ConnectionInfo[]{
new ConnectionInfo(1, 0, "149.154.167.40", 443)
};
apiState = new ApiState(connections);
doReqCode(connections);
private void doReqCode(connections){
var args = new SocketAsyncEventArgs();
I don't see where the code could break, maybe a more detailed description of your problem would be helpful
TcpClient tcpClient = new TcpClient();
As i tried the code, it mostly seemd to me as if the port was either blocked or already in use. Maybe u have a permission problem there. At least i didnt manage to get a Socket to work with the code like that.
Also i didnt dive to deep in your code, but you are using port 443. This is a reserved port with limited access.
You can get started with this, but I have written it in vb.net, not C#.
It will walk you through getting started building your own Telegram-API from scratch.
Also try and get familiar with the online documentation, it's hard but the step by step explanation I gave in that link above on generating your AuthKey, should get you started.
Good Luck
I wrote an app to automatically connect to our different Firewalls. All of them work with the same frontend. We telnet to the IP and they give the message LOGIN or LOGOUT and ask for a username or password.
I used this code:
public static void ConnectToFirewall(string strUsername, string strPassword, string strFirewallIp)
{
IPAddress[] ipaIpAddressCollection = Dns.GetHostAddresses(strFirewallIp);
IPEndPoint ipeIpEndPoint = new IPEndPoint(ipaIpAddressCollection[0], intPort);
Socket sckSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sckSocket.Connect(ipeIpEndPoint);
string strData = strUsername + "\r\n"+ strPassword + "\r\n";
byte[] bytData = new byte[1024];
bytData = Encoding.ASCII.GetBytes(strData);
sckSocket.Send(bytData);
byte[] bytDataReceived = new byte[1024];
int intData = sckSocket.Receive(bytDataReceived);
sckSocket.Close();
}
If I am not logged in, when I telnet to it, I receive the message: LOGIN, username: / Password:.
If I am logged on, I receive LOGOUT, username: / Password.
This works perfectly well with the above method for half of my firewalls, it does not seem to work (I keep getting login as if I had not tried to pass credentials).
I also tried it with
TcpClient tcpConnection = new TcpClient(myip,myport);
but this gives the same result. It works for certain firewall ip's. fails for others. They are all in the same domain.
Does anyone have idea how I could get past this or what steps I could undertake to troubleshoot this or what may be the cause of some server not accepting this method, allthough it does accept if I telnet to it?
Any help or suggestions are appreciated.
Many thanks in advance.
When you call sckSocket.Send(bytData), how does the socket know to send only the portion of the bytData that has been initialized with the username and password? I have a feeling that Send() will send the entire 1024 bytes along, most of which will be 0x00 bytes. I would not expect a router to handle this gracefully.
I've seen systems that accepted the password only after the prompt for the password has been generated and sent. Try sending the username and password with two separate requests. If your environment makes it feasible to set the TCP_NODELAY socket option to disable Nagle's algorithm, it might help to get the username string sent along more quickly. (I wouldn't bother with this unless you also split apart sending the username from the password.)
I am working on a project where I have to validate the given SMTP server i.e in a textbox user will provide the detail and then he will click on a test button. I want to check whether the server entered by the user is an Smtp Server or not?
Any Idea??
You might want to improve on this quick code with proper exception handling and maybe also setting the timeouts - it takes about 15 seconds to fail if it can't connect but that might be a limitation of the TCP/IP handshaking.
And sending a QUIT command as Curt suggested would be nice.
private bool ValidSMTP(string hostName)
{
bool valid = false;
try
{
TcpClient smtpTest = new TcpClient();
smtpTest.Connect(hostName, 25);
if (smtpTest.Connected)
{
NetworkStream ns = smtpTest.GetStream();
StreamReader sr = new StreamReader(ns);
if (sr.ReadLine().Contains("220"))
{
valid = true;
}
smtpTest.Close();
}
}
catch
{
}
return valid;
}
Attempt to connect to the SMTP port, and ensure you get a line back from it that starts with "220 " and contains the letters "SMTP". A typical example response would be:
220 prod.monadic.cynic.net ESMTP Postfix (2.5.5)
Then be polite and send "QUIT\r\n" to hang up.
You can do some further testing, if you like, such as testing that the user can likely deliver messages. For this, you'd send a HELO command with your hostname (or any string, really), a MAIL FROM command using the user's e-mail address, and a RCPT TO:<example#example.com>. Most servers at that point will tell you if relaying is not allowed. (I'm assuming you're doing this from the computer from which you will later be sending mail.) So long as you QUIT after that, rather than issuing a DATA command and
the message data, nothing will be sent.
Here's an example session, done from the shell using the "netcat" command, showing that my server exists, but will not relay mail for people from random IP addresses.
$ nc prod.monadic.cynic.net. 25
220 prod.monadic.cynic.net ESMTP Postfix (2.5.5)
HELO cynic.net
250 prod.monadic.cynic.net
MAIL FROM:<cjs#cynic.net>
250 2.1.0 Ok
RCPT TO:<example#example.com>
554 5.7.1 <example#example.com>: Relay access denied
QUIT
221 2.0.0 Bye
$
The client connects to the server using GenuineChannels (we are considering switching to DotNetRemoting). What I mean by find is obtain the IP and port number of a server to connect to.
It seems like a brute-force approach would be try every IP on the network try the active ports (not even sure if that's possible) but there must be a better way.
Consider broadcasting a specific UDP packet. When the server or servers see the broadcasted UDP packet they send a reply. The client can collect the replies from all the servers and start connecting to them or based on an election algorithm.
See example for client (untested code):
using System.Net;
using System.Net.Sockets;
[STAThread]
static void Main(string[] args)
{
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
socket.Bind(new IPEndPoint(IPAddress.Any, 8002));
socket.Connect(new IPEndPoint(IPAddress.Broadcast, 8001));
socket.Send(System.Text.ASCIIEncoding.ASCII.GetBytes("hello"));
int availableBytes = socket.Available;
if (availableBytes > 0)
{
byte[] buffer = new byte[availableBytes];
socket.Receive(buffer, 0, availableBytes, SocketFlags.None);
// buffer has the information on how to connect to the server
}
}
I'd say the best way is to use Bonjour/Zeroconf/mDNS for C#; a lot of thought went into making it play nice with the network; IE it pings less frequently over time if possible, etc. There's Mono.Zeroconf, and I read there's an older .NET project in the Apple SDK but I haven't found it.
So the easiest would be to install Bonjour for Windows, then get the Windows Binaries for Mono.Zeroconf try the example MZClient.exe drop the Mono.Zeroconf.dll and/or Mono.Zeroconf.Providers.Bonjour.dll into your project references and go.
Something like this:
var service = new Mono.Zeroconf.RegisterService {
Name = "Use Me for Stuff",
RegType = "_daap._tcp",
ReplyDomain = "local.",
Port = 0024200,
TxtRecord = new Mono.Zeroconf.TxtRecord {
{"I have no idea what's going on", "true"}}
};
service.Register();
var browser = new Mono.Zeroconf.ServiceBrowser();
browser.ServiceAdded +=
delegate(object o, Mono.Zeroconf.ServiceBrowseEventArgs args) {
Console.WriteLine("Found Service: {0}", args.Service.Name);
args.Service.Resolved +=
delegate(object o, Mono.Zeroconf.ServiceBrowseEventArgs args) {
var s = args.Service;
Console.WriteLine(
"Resolved Service: {0} - {1}:{2} ({3} TXT record entries)",
s.FullName, s.HostEntry.AddressList[0], s.Port, s.TxtRecord.Count);
};
args.Service.Resolve();
};
browser.Browse("_daap._tcp", "local");
Just wanted to point out an alternative Zeroconf NuGet package: Zeroconf. It does not have any native dependencies, so you don't need to install Bonjour for Windows or anything else.
It has support for .NET 4.5, WP8 and Win8.
WS-Discovery is a protocol intended for this purpose. It has a few different variations, different flavors of broadcasting and proxies. http://en.wikipedia.org/wiki/WS-Discovery
.NET WCF4 implements this.
Have the server listen for broadcast on a specific port on the network (must use UDP), When client starts have it broadcast some "ping" request on that port. when the server sees a "ping" it send back a message with the TCP address and port required for the client to connect to it.