OpenSSL with raw sockets for EAP-TLS - c

I want to design an EAP-TLS client. As the protocol works on the ethernet layer, I am using raw sockets in C and designing the handshake step by step. I wanted to get the TLS data into the packet i designed using OpenSSL. The examples I found online used SSL_Connect() with a socket descriptor and sent the data. I however want to copy the data into the buffer i will send using the raw sockets. Is there any way to do this ? Thank you!

If you want to have everything in your own buffer and not send directly to the socket you have to use not a file descriptor, but a memory BIO as the lower layer for SSL and then you can use the usual SSL_ functions on top of it. You might have a look at Directly Read/Write Handshake data with Memory BIO. A working implementation you'll find in AnyEvent::Handle. Although this is Perl the usage of the BIO_ functions is the same.

Related

Check number of correctly received packets - Socket Programming

I am writing an application in C using socket programming. I wish to send the data from the server node to the client node. I use the read and write commands on the socket descriptor to get and send the data over the network respectively. Since, the underlying protocol used is TCP/IP, finally I receive the correct data. Is it possible to check on the client side that to receive the data correctly, how many packets were actually lost and re-transmitted? I am writing this application in Linux (debian) environment.
Any help is highly appreciated !
-Rahulkumar
/proc/net/tcp has a field retrnsmt, you simply need to find your socket in this list.
An alternative would be to use the TCP_INFO sockopt. The current layout of struct tcp_info can be found in linux/tcp.h. The field you want to use is probably tcpi_retrans.

Confused about OpenSSL non-blocking I/O

In general, the OpenSSL library (C API) seems to offer two ways to do everything: you can either use plain system sockets configured to your liking, or you can use OpenSSL BIO objects which are sort of like streams.
However, I'm often confused by some of the duplicated functionality. For example, how do you make an SSL connection non-blocking? One way seems to be to simply access the underlying file descriptor and set it to non-blocking using fcntl. But there is also an OpenSSL API function called BIO_set_nbio which takes in a BIO* object and sets it to non-blocking mode.
So what is the best way to set up a non-blocking SSL socket? What happens if you pass OpenSSL a native file descriptor which is already set to non-blocking mode via fnctl? Do you still need to specifically call BIO_set_nbio to make the BIO object non-blocking?
I think most people prefer the BIO interface, but the BIO routines just use whatever native non-blocking socket APIs that are available on the platform. I don't know what happens if you mix and match.
Note that non-blocking I/O for SSL is much trickier than for TCP in general. If you don't understand this going in you're going to be torturing yourself. There are books by John Viega and another by Eric Rescorla that go into this, and you can certainly read the OpenSSL mailing list to get a sense of the heartburn this has caused. Some good code examples showing non-blocking SSL programming with OpenSSL are contained in the software for the TOR project, and the curl utility.

send a HTTP request using raw socket and WinPcap

as part of my project, I'm trying to send IP packets that contain HTTP requests to Google. I'm using Winpcap library and VC++. Currently, I have the TCP three-way handshaing packets done, but I'm stuck on sending the actual HTTP request packet after I send the TCP ACK packet. When I capture the packets using wireshark, this packet is marked "TCP segment of a Reassembled PDU". The protocol column is 'TCP' not 'HTTP' also. What's wrong? How would I send HTTP packets in this way?
You aren't necessarily doing anything wrong.
By default, Wireshark hands the TCP data to a higher level protocol handler - in this case, one that tries to reassemble entire HTTP requests and responses. It attaches the reassembled message to the final packet in the sequence, and labels the other packets with "TCP segment of a reassembled PDU":
You can disable this reassembly feature to examine the individual packets:
Edit -> Preferences -> Protocols -> TCP
Uncheck "Allow subdissector to reassemble TCP streams"
Why are you using WinPCap to send the packets? You should be using normal sockets instead. Better, use a socket library that implements the HTTP protocol for you, such as curl, or even Microsoft's own WinInet or WinHTTP APIs.
I would highly recommend that you learn the basis of the HTTP protocol before you try this if you're planning on extending this. Mess with doing raw sockets and throwing get requests; read some source code.
However, I wouldn't really see the point of pcap. You should be able to use the Wininet library if you don't want to have to code the actual socket:Wininet lib
However, if you're wanting to code raw sockets, I would go ahead and use winsocks. The difference between HTTP and TCP is hard for some to understand; HTTP is BASED on TCP, so they are technically all in the same, TCP is used for quite literally thousands of applications. Most of the connections on your computer are TCP.
If you're trying to intercept a connection as a MITM attack with a pcap program to send an HTTP request, I would probably learn some programming in Pcap. There are numerous tutorials for this, such as this one.
PS: Look up a winsocks tutorial as it's quite hard to understand for beginners. Also, winpcap isn't supported on all systems, and it can be (in some cases) a pain to install. It would honestly be better to use winsocks to do this. Wininet has much more support, and I (don't hold me on this) believe that all of the W2K+ builds all have wininet, so for compatability (which I don't really think is a problem for you) issues I would use wininet or winsocks.
Probably you are not finishing the request with \r\n twice.
If you send the GET / HTTP/1.0\r\n string, you will not receive any packets.
You must send this string: GET / HTTP/1.0\r\n\r\n.

Can I make a "TCP packet modifier" using tun/tap and raw sockets?

I have a Linux application that talks TCP, and to help with analysis and statistics, I'd like to modify the data in some of the TCP packets that it sends out. I'd prefer to do this without hacking the Linux TCP stack.
The idea I have so far is to make a bridge which acts as a "TCP packet modifier". My idea is to connect to the application via a tun/tap device on one side of the bridge, and to the network card via raw sockets on the other side of the bridge.
My concern is that when you open a raw socket it still sends packets up to Linux's TCP stack, and so I couldn't modify them and send them on even if I wanted to. Is this correct?
A pseudo-C-code sketch of the bridge looks like:
tap_fd = open_tap_device("/dev/net/tun");
raw_fd = open_raw_socket();
for (;;) {
select(fds = [tap_fd, raw_fd]);
if (FD_ISSET(tap_fd, &fds)) {
read_packet(tap_fd);
modify_packet_if_needed();
write_packet(raw_fd);
}
if (FD_ISSET(raw_fd, &fds)) {
read_packet(raw_fd);
modify_packet_if_needed();
write_packet(tap_fd);
}
}
Does this look possible, or are there other better ways of achieving the same thing? (TCP packet bridging and modification.)
There were some apps I used years ago to do some TCP/IP packet manipulation for testing a firewall: fragoute and fragtest. Looks like they haven't been touched in years, but they might give you some ideas of what to do in your code.
You might want to consider using a LD_PRELOAD library to hook the functions that it uses to send the data out (send(), write() etc).
That wouldn't involve any kernel messing-around at all.
Another option is to NAT the outbound connections to a local proxy which can read the data, make whatever modifications, and send it all out to the real destination (with some options to prevent it being NAT'd again and going round in circles)
You can use the click modular router. It is a software router implemented entirely in C++. Click allows you to capture packets as they pass through elements in the router where you can modify or collect statistics as needed. As a kernel module, you completely override the linux routing mechanism and as a userland binary you simply get a duplicate (as you mention in your post) of each packet from the interface. Packets can be directed through the Click graph by way of pcap filters and a variety of other mechanisms.
If you are headed down the bridge route, I think this provides the most direct support for what you are looking to do as you can use tun/tap, to/from host or to/from device capture methods as you require.

SSL wrapper stream in C

I have a simple stream_t type in C with your basic read/write operations, and support for multiple underlying implementations using function pointers. So a stream could be backed by a file, a char buffer, etc.
One stream type is a standard POSIX socket, and I would like to code a wrapper stream that will add SSL support to an existing stream, similar to .NET's SslStream. So I could write something like this:
stream_t *socket = something();
// wrap existing stream and perform handshake as client
stream_t *ssl_stream = ssl_stream_create(socket);
ssl_stream_authenticate_as_user(ssl_stream);
// now all read/writes are encrypted and passed through to the wrapped stream
I have written some SSL socket code before using OpenSSL's BIO_new_connect(...) etc. but this is a higher level API than what I need. Does OpenSSL expose the functions I would need to manually perform the handshake and encryption? Or is there some other library I can use?
I don't know any libraries you can use but you can find plenty of samples. Most applications in C would have to do the same for their TCP code so SSL and raw socket versions don't differ too much.
For example, check out ssl_unix.c from Pine IMAP,
https://svn.cac.washington.edu/public/alpine/snapshots/imap/src/osdep/unix/
It does exactly what you are describing with OpenSSL.
I have used a BIO_s_mem as a cover for SSL socket operations. I would read from and write to the socket myself (rather than giving the handle to OpenSSL and having it do the reading/writing). The handshake is done when you call SSL_accept (on the server side) or SSL_connect (on the client side). Other than that, just call SSL_read and SSL_write to do the reading and writing.

Resources