OpenSSL: Specify packet size of application data - ssl

When I do something like this, apps/openssl s_client -connect 10.102.113.3:443 -ssl3, client-server communication is created using openSSL.
Now, I want to send application data from the client to the server. For example, after doing apps/openssl s_client -connect 10.30.24.45:443 -ssl3, I get something like this:
...certificate and session details...
---
GET /path/to/file
The GET /path/to/file all goes in one SSL record. I want to send it in multiple records.
I assume I have to edit apps/s_client.c, and find the place where the SSL_write or similar happens.
How do I go about something like that?

For a properly designed application the TCP packet sizes and SSL frame sizes should not matter. But there are badly designed applications out there which expect to get like the HTTP request inside a single read, which often means that it must be inside the same SSL frame. If you want to run tests against applications to check for this kind of behavior you either have to patch your s_client application or you might use something else, like
#!/usr/bin/perl
use strict;
use IO::Socket::SSL;
my $sock = IO::Socket::SSL->new('www.example.com:443') or die "$!,$SSL_ERROR";
print $sock "GE";
print $sock "T / HT";
print $sock "TP/1.0\r\n\r\n";
This will send the HTTP request header within 3 SSL frames (which might still get put together into the same TCP packet). Since on lots of SSL stacks (like OpenSSL) one SSL_read reads only a single SSL frame this will result in 3 reads necessary to read the full HTTP request.

Okay, I figured out that I needed to change the number of bytes I'm writing using the SSL_write.
This is a code snippet, starting at line 1662 of s_client.c:
if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))
{
k=SSL_write(con,&(cbuf[cbuf_off]), (unsigned int)cbuf_len);
.......
}
To make the application data be sent in multiple records instead of just the one, change the last parameter in the SSL_write.
For example, do this:
if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))
{
k=SSL_write(con,&(cbuf[cbuf_off]), 1);
.......
}
This will result in something like this:
Notice the multiple records for Application Data instead of just the one.

Related

Building Wireshark LDAP filter for future scripting

all
On our environment we have several servers still using ldap for authentication and I need to filter ldap requests for 8 hours to have an overview on how many different accounts we may have exposed.
The issue is I cannot create captures that are too large. (Just for an example, using a filter to ldap port and marking the flags of a TCP request I barely can capture 3 minutes before my capture is hitting 100MB).
I wonder if there is a way to build a capture filter that would look for a HEX on the DATA part of the packet.
Does anyone have any clue on how I would be able to do that?
Currently I am using a capture filter like:
port 389 && tcp[13] == 24
and a display filter like:
ldap.bindRequest_element && ldap.messageID==1
Another issue is that doing this I couldn't come up with a script that would strip the username so I could inform all possibly compromised users to change their PWDs.
Thanks in advance
I found a way to do this.
Just for people that are still curious or would need something similar I used the following:
port 389 && tcp[((tcp[12:1] & 0xf0) >> 2) + 2:2] = 0x0201 && tcp[((tcp[12:1] & 0xf0) >> 2) + 4:1] = 0x01
This check the data part of the packet and since some of the bytes are always in the same position and are all the same for a ldap bind request with message id 1 I used that to build the filter.
Cheers.

Wireshark dissector that works with tls/ssl

I have a protocol that uses SSL/TLS over a non-standard port and transmits non-standard data (not http) through it. I'm trying to make a wireshark dissector (in lua) to dissect this protocol.
How do I do this? I can register a dissector that gets called for tcp fragments on that port
local dissector_table_tcp = DissectorTable.get("tcp.port")
dissector_table_tcp:add(1234, myprotocol)
I can get the SSL dissector to then decode all the fragments as SSL
function myprotocol.dissector(tvb, pinfo, root)
local ssl_dissector = Dissector.get("ssl")
local ssl_dissected_len = ssl_dissector:call(tvb, pinfo, root)
pinfo.cols.protocol:set("My Protocol")
At this point, if I have a premaster key file set in Wireshark (Preferences->Protocols->SSL->Master key file), I can see the decrypted contents of the packets and all is good. Sort of.
But I want to create fields for my protocol and put them in the protocol tree. How do I get at the decrypted data that the ssl dissector produced?
Update:
I'm trying to muddle through this as best as I can; there's no tutorial on how exactly you're supposed to do this. It sort of looks like Wireshark has a programming model based on fields/variables that are populated by dissectors, and that in theory it should be possible to interrogate those variables to find the output of a dissector.
To that end, I've been running the SSL dissector and then looking at fields that it declares, but it doesn't actually seem to populate them. When I run a post-dissector after the SSL dissector, none of the seemingly-useful fields, like ssl.segments or ssl.segment.data, are set:
protocol_foo = Proto("foo", "Foo protocol")
port = 4172
g_field_segment = Field.new("ssl.segment")
g_field_segment_data = Field.new("ssl.segment.data")
g_field_segments = Field.new("ssl.segments")
g_field_reassembled_data = Field.new("ssl.reassembled.data")
function protocol_foo.dissector(tvb, pinfo, root)
print("====== protocol_foo")
for k,v in pairs({ g_field_segment, g_field_segment_data, g_field_segments, g_field_reassembled_data }) do
if v() ~= nil then
print("Field " .. v.name .. " is NOT nil")
else
print("Field " .. v.name .. " is nil")
end
end
end
-- post-dissector registration
local ssl_dissector = Dissector.get("ssl")
local dissector_table_tcp = DissectorTable.get("tcp.port")
dissector_table_tcp:add(port, ssl_dissector)
register_postdissector(protocol_foo)
When I run this code on my protocol, none of those ssl.segment* variables test positive; lots of variables (like the ssl.handshake.*) variables do test positive (at least with handshake pdus), but not the ones with the decrypted contents.
Does anyone have any ideas?

How to get peer certificate in cowboy_http_handler

My question for today: is there an official way to obtain peer ssl socket information (peer certificate to be exact) in cowboy_http_handler's Handler:handle(Req, State)?
Of course, I can scrape Req tuple (peer socket is the second field as of today) with erlang:element/2, but this is not future-proof and just doesn't look right.
Thanks in advance!
There is an exported call:
cowboy_req:get(socket, Req)
It returns the socket, or just about everything else there is in the Req object, currently:
bindings
body_state
buffer
connection
headers
host
host_info
meta
method
multipart
onresponse
path
path_info
peer
pid
port
qs
resp_body
resp_compress
resp_headers
resp_state
socket
transport
version
I'm not sure if it is in the documentation, I can't see it, but it's a lot better and less likely to fail than just getting a numbered element value out, and you can always add a unit test that checks that it works, so if it does get stamped/broken at some point you get a heads up. I don't expect it'll go anywhere though.

Libevent 2 - write callback / infinite loop

I'm playing with Libevent as a server and I'm having a problem
Basically I'm using the example at the bottom of this page, http://www.wangafu.net/~nickm/libevent-book/Ref6_bufferevent.html:
I have the main/accept/readcb working well - however trying to understand the writecb.
Before I go further I want to make sure I have this correct.
When a client send (curl in this instance) sends some JSON, this is called in the read_callback, when I want to write back to the curl I use the write_callback.
the problem I have in short, when I do a curl with json. It requests that the server sends a http/1.1 100 continue before sending the JSON. I could ignore that but would rather not.
So this is what I have for my write callback:
void writecb(struct bufferevent *bev, void *ctx){
struct evbuffer *tmp = evbuffer_new();
evbuffer_add_printf(tmp, "HTTP/1.1 100 Continue\r\n\r\n");
bufferevent_write_buffer(bev, tmp);
evbuffer_free(tmp);
printf("finish sending data back to client!\n");
}
What happens is when I do a curl statement:
curl -vv -H "Content-Type: application/json" --data #test.json http://localhost:40714
On the console there is an infinite loop.
However if I put this code within the readcb, it works like a charm. So my question, what is the point of writecb? Is it when you finalize a write and what to close a connection you send 'stuff'?
The point of writecb is opposite to readcb: writecb is invoked by libevent automatically when there is enough room in the OUTPUT side of bufferevent for some new data to be written into.
Here you described a good example of infinite loop:
writecb was invoked by libevent (because there is enough room on OUTPUT side)
inside writecb you generating new data and writing it into the OUTPUT by bufferevent_write_buffer. Then writecb returns context back to libevent main loop.
libevent is passing all the data from OUTPUT to the kernel. And when done, libevent sees that a free place became available in OUTPUT buffer. This generates next writecb event and the callback is invoked again... And here is the infinite loop.

How can I load balance FastAGI?

I am writing multiple AGIs using Perl that will be called from the Asterisk dialplan. I expect to receive numerous similtaneous calls so I need a way to load balance them. I have been advised to use FastAGI instead of AGI. The problem is that my AGIs will be distributed over many servers not just one, and I need that my entry point Asterisk dispatches the calls among those servers (where the agis reside) based on their availability. So, I thought of providing the FastAGI application with multiple IP addresses instead of one. Is it possible?
Any TCP reverse proxy would do the trick. HAProxy being one and nginx with the TCP module being another one.
A while back, I've crafted my own FastAGI proxy using node.js (nodast) to address this very specific problem and a bit more, including the ability to run FastAGI protocol over SSL and route requests based on AGI request location and parameters (such as $dnis, $channel, $language, ...)
Moreover, as the proxy configuration is basically javascript, you could actually load balance in really interesting ways.
A sample config would look as follow:
var config = {
listen : 9090,
upstreams : {
test : 'localhost:4573',
foobar : 'foobar.com:4573'
},
routes : {
'agi://(.*):([0-9]*)/(.*)' : function() {
if (this.$callerid === 'unknown') {
return ('agi://foobar/script/' + this.$3);
} else {
return ('agi://foobar/script/' + this.$3 + '?callerid' + this.$callerid);
}
},
'.*' : function() {
return ('agi://test/');
},
'agi://192.168.129.170:9090/' : 'agi://test/'
}
};
exports.config = config;
I have a large IVR implementation using FastAGI (24 E1's all doing FastAGI calls, peaks at about 80% so that's nearly 600 Asterisk channels calling FastAGI). I didn't find an easy way to do load balancing, but in my case there are different FastAGI calls: one at the beginning of the call to validate the user in a database, then a different one to check the user's balance or their most recent transactions, and another one to perform a transacion.
So what I did was send all the validation and simple queries to one application on one server and all the transaction calls to a different application on a different server.
A crude way to do load balancing if you have a lot of incoming calls on zaptel/dahdi channels would be to use different groups for the channels. For example suppose you have 2 FastAGI servers, and 4 E1's receiving calls. You can set up 2 E1's in group g1 and the other 2 E1's in group g2. Then you declare global variables like this:
[globals]
serverg1=ip_of_server1
serverg2=ip_of_server2
Then on your dialplan you call FastAGI like this:
AGI(agi://${server${CHANNEL(callgroup)}}/some_action)
On channels belonging to group g1, that will resolve to serverg1 which will resolve to ip_of_server1; on channels belonging to group g2, CHANNEL(callgroup) will resolve to g2 so you get ${serverg2} which resolves to ip_of_server2.
It's not the best solution because usually calls start coming in on one span and then another, etc so one server will get more work, but it's something.
To get real load balancing I guess we would have to write a FastAGI load balancing gateway, not a bad idea at all...
Mehhh... use the same constructs that would apply to load balancing something like web page requests.
One way is to round robin in DNS. So if you have vru1.example.com 10.0.1.100 and vru2.example.com 10.0.1.101 you put two entries in DNS like...
fastagi.example.com 10.0.1.100
fastagi.example.com 10.0.1.101
... then from the dial plan agi(agi://fastagi.example.com/youagi) should in theory alternate between 10.0.1.100 and 10.0.1.101. And you can add as many hosts as you need.
The other way to go is with something a bit too complicated to explain here but proxy tools like HAProxy should be able to route between multiple servers with the added benefit of being able to "take one out" of the mix for maintenance or do more advanced balancing like distribute equally based on current load.