C# - Socket to log on to Firewall - c#

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.)

Related

send password as command via Telnet in C#

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!

Can't find all machine name on local network

We're trying to obtain all ip addresses and hostnames of machines on local network, we have a display box(BrightSign box) which is connected to local network and we want to have all information about that box. We can find ip address of it, but cannot get host name. So we can't determine which ip adresses is assigned to that box. (We can learn the ip address of the box by using its own program; but we want to detect automatically)
here the code we use in c#
`
public void scan(string subnet)
{
Ping myping;
PingReply reply;
IPAddress addr;
IPHostEntry host;
for (int i = 1; i < 255; i++)
{
string subnetn = "." + i.ToString();
myping = new Ping();
//string data = "aa";
//byte[] buffer = Encoding.ASCII.GetBytes(data);
//PingOptions optionss = new PingOptions(64, true);
int timeout = 1000;
reply = myping.Send(subnet + subnetn);
if (reply.Status == IPStatus.Success)
{
try {
addr = IPAddress.Parse(subnet+subnetn);
host = Dns.GetHostEntry(addr);
txtHosts.AppendText(subnet + subnetn + host.HostName.ToString()+"\n");
}
catch {
}
}
}
}`
if we use this code, system can detect all ip but not host names belongs to telephone and the box i mentioned.
Briefly, we need to have all machine name and ip addresses on local network.
So, do you guys have any idea what's the problem and what can we do to solve this issue. We made some research and tried some ways. We tried to send ping the ip address which we cannot take the hostname and we realized that if ttl of machine is set to 64, we cannot take the hostname, but if its ttl is 128, we can manage to learn the hostname, i also adjusted ping settings to test this challenge, but i still have problem.
I am looking forward to hearing your response.
Thank you all.
Machine name could be DNS or NETBIOS or something else. I recommend you check out NMAP and see what it can do. If you want to emulate that, you can ask about a specific requirement. For example, getting a DNS name means querying the DNS server, a computer wont reply with a name just from an ICMP ping. If the computer security settings allow it, you can do a netbios query, or use WMI, or if you are in a domain, query the domain server.
I don't know what brightsign is, but there is no law that says a device must have a DNS name, some appliances just use IP address and thats it. Also there's no law that says a device must respond to ping or any other protocol.

How to get the MAC address prior to connection?

I have a situation where I ping a range of IPs in the network. Then, I try to connect to the successful pings.
My aim is to connect to specific equipment that has a specific MAC prefix. For example, when I ping a range of 100 IPs, I might get 20 replies. These replies include computers, printers, and possibly the hardware I am trying to connect.
Currently what happens is that when I try to connect to anything other than the hardware I would like (i.e computer, printer) I get a timeout connection.
This is fine, however, it is not efficient. I would like to filter out the successful ping list by using the MAC address, however, I have not yet been able to find a solution that allows me to seek a MAC address prior to connecting the hardware.
I have looked through most the MAC questions on here, but none fit my needs.
Any ideas??
I was able to find the solution here: http://pinvoke.net/default.aspx/iphlpapi/SendARP.html
The following method returns the MAC
internal static string GetMAC(string ip)
{
IPAddress dst = IPAddress.Parse(ip); // the destination IP address Note:Can Someone give the code to get the IP address of the server
byte[] macAddr = new byte[6];
uint macAddrLen = (uint)macAddr.Length;
if (SendARP((int)dst.Address, 0, macAddr, ref macAddrLen) != 0)
throw new InvalidOperationException("SendARP failed.");
string[] str = new string[(int)macAddrLen];
for (int i = 0; i < macAddrLen; i++)
str[i] = macAddr[i].ToString("x2");
return string.Join(":", str);
//Console.WriteLine(string.Join(":", str));
}

How to validate SMTP server

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
$

What is the best way for a client app to find a server on a local network in C#?

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.

Categories