openssl SMIME and multipart messages - encryption

I need to send an encrypted email with a binary attachment from bash. I've read the RFC, and the openssl docs as well as a couple additional posts here in SF to no avail.
So far the process I understand goes like this:
Create a MIME message
use openssl smime to encrypt it generating additional headers for the envelope. This should be signed with my own private key but encrypted with the recipient's public key.
pipe this output to sendmail
The receiver should be able to decrypt the whole thing in outlook.
However what I'm seeing is a bit of garbled text. If anyone can shine some light where I'm messing up, I'd be thankful.
What follows are the nitty gritty details:
1. MIME Message
From: <FROM>
To: <TO>
Subject: <SUBJECT>
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="<BOUNDARY>"
--<BOUNDARY>
Content-Type: text/plain; charset=utf-8
<TEXT>
--<BOUNDARY>
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename= "<FILENAME>"
<BASE64_DATA>
--<BOUNDARY>
2. The signing & Encrypting:
SIGNED=$(openssl smime -sign -in mime.txt -signer MyPublic.cer -inkey MyPrivate.key)
ENCRYPTED=$(openssl smime -encrypt -subject "Work damn you" RecipientPublic.cer <<< $SIGNED)
3. The Sending
echo "$ENCRYPTED" | sendmail recipient#hush-hush.com

so... after blood and tears it is done.
Lessons learned:
Also the Content-Type: multipart/alternative; should be Content-Type: multipart/mixed; else the email clients will be confused and show garbage.
#dave_thompson_085 's comment of the missing -- at the end were spot on. That was part of the whole drama.
be any funky word-wrapping that will mess up the encoding (don't ask me why).
In Bash, as in real-life, quotes are important. So ENCRYPTED=$(openssl smime -encrypt -subject "Work damn you" RecipientPublic.cer <<< $SIGNED) should really be ENCRYPTED=$(openssl smime -encrypt -subject "Work damn you" RecipientPublic.cer <<< "$SIGNED")
Openssl will take care of enveloping the appropriate headers, so there's no need to do anything here except the -subject flag.

Related

Setting HTTP response headers with Kemal

I want implement this answer in Kemal.
My current setup has a pdf file in app/public/map.pdf, and the following code in my main crystal file:
require "kemal"
#...
get "/map.pdf" do |env|
env.response.headers["Content-Type"] = "application/pdf"
env.response.headers["Content-Disposition"] = %(inline;filename="myfile.pdf")
end
Kemal.run
When I test my code by opening localhost:3000/map.pdf in a browser (firefox), it prompts to download the file (while I want it to attempt to display it). And curl -I results in the following:
HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Kemal
Content-Type: application/octet-stream
ETag: W/"1494983019"
Content-Length: 1170498
Where I would hope to see Content-Type: application/pdf.
Kemal author here,
If the headers are ok you should be good to go with send_file. However be sure that the route name and file are not the same. In this case the route is /pdf
get "/pdf" do |env|
env.response.headers["Content-Type"] = "application/pdf"
env.response.headers["Content-Disposition"] = %(inline;filename="map.pdf")
send_file env, "./public/map.pdf"
end
Where I would hope to see Content-Type: application/pdf.
The point is that Content-Disposition doesn't exist as a header.
Maybe you don't send any headers at all for some reason.
For example in PHP, if your script outputs a single byte before it sends the headers then no headers will be sent; only the headers before the first output.
If you set a http header after some data is sent then the header will be ignored.

How to send a POST request using HTTPie?

I have a basic silex application, and I try to test it using HTTPie. Yet when posting using:
http POST http://localhost:1337 data="hello world"
The data, that I get from the Request object via:
$data = $request->request->get('data');
will always be empty. What is the problem here?
It was an httpie usage problem as the form flag was necessary, as silex requires the parameters to be form-encoded, yet the default of HTTPie is to pass a JSON object.
$ http --form POST http://localhost:1337 data="hello world"
HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: close
Content-Type: application/json
Date: Wed, 14 Oct 2015 15:04:09 GMT
Host: localhost:1337
X-Powered-By: PHP/5.5.9-1ubuntu4.13
{
"message": "hello world"
}
Just to clarify what kOpernikus said, when you are making a POST request using httpie, use the following syntax:
http --form post :3000/register username="gilbert" password="stackoverflow!"
Alternatively, since forms are for post requests you can leave out post and also abbreviate --form to -f like so:
http -f :3000/register username=gilbert password=stackoverflow!
EDIT (thanks to Aerials)
To pass csrf token as header in the post request do:
http --form POST http://localhost:8000/login/ username=user password=pass X-CSRFToken:assQ$%auxASDLSIAJSd

Uploading file gets Bad Request from the server

I am trying to send a file using HTTP from a C++ application (no HTML-boxes). The server keeps answering Code 400/ Bad Request.
To keep it simple, I have changed manually the content of the file to a simple string (later on, I will need to upload real binary files).
the POST request is the following:
POST /post.php HTTP/1.0
Host: posttestserver.com
Accept: */*
Content-Type: multipart/form-data; boundary=BOUNDARY
--BOUNDARY
Content-Disposition: form-data; name="userfile"; filename="example.txt"
Content-Type:text/plain
123ABC
--BOUNDARY--
Connection: close
Any idea what is going on?

How do I POST form data with UTF-8 encoding by using curl?

I would like to POST (send) some form data to a webserver using cURL on a terminal-prompt.
This is what I got so far:
curl --data-ascii "content=derinhält&date=asdf" http://myserverurl.com/api/v1/somemethod
The problem is that the umlaute ("äöü") are replaced by "?" when I receive the post request on the server.
I think I need to use an UTF-8 encoding for the POST request.
Does anybody know how I can achieve this?
You CAN use UTF-8 in the POST request, all you need is to specify the charset in your request.
You should use this request:
curl -X POST -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" --data-ascii "content=derinhält&date=asdf" http://myserverurl.com/api/v1/somemethod

Compojure: getting the body from a POST request from which the Content-Type header was missing

Given this snippet:
(defroutes main-routes
(POST "/input/:controller" request
(let [buff (ByteArrayOutputStream.)]
(copy (request :body) buff)
;; --- snip
The value of buff will be a non-empty byte array iff there's the Content-Type header in the request. The value can be nonsencial, the header just has to be there.
However, I need to dump the body (hm... that came out wrong) if the request came without a content type, so that the client can track down the offending upload. (The uploading software is not under my control and its maintainers won't provide anything extra in the headers.)
Thank you for any ideas on how to solve or work around this!
EDIT:
Here are the headers I get from the client:
{
"content-length" "159",
"accept" "*/*",
"host" (snip),
"user-agent" (snip)
}
Plus, I discovered that Ring, using an instance of Java's ServletRequest, fills in the content type with the standard default, x-www-form-urlencoded. I'm now guessing that HTTPParser, which supplies the body through HTTPParser#Input, can't parse it correctly.
I face the same issue. It's definitely one of the middleware not being able to parse the body correctly and transforming :body. The main issue is that the Content-Type suggest the body should be parsable.
Using ngrep, I found out how curl confuses the middleware. The following, while intuitive (or rather sexy) on the command line sends a wrong Content-Type which confuses the middleware:
curl -nd "Unknown error" http://localhost:3000/event/error
T 127.0.0.1:44440 -> 127.0.0.1:3000 [AP]
POST /event/error HTTP/1.1.
Authorization: Basic SzM5Mjg6ODc2NXJkZmdoam5idmNkOQ==.
User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3.
Host: localhost:3000.
Accept: */*.
Content-Length: 13.
Content-Type: application/x-www-form-urlencoded.
.
Unknown error
The following however forces the Content-Type to being opaque and the middleware will not interfere with the :body.
curl -nd "Unknown error" -H "Content-Type: application/data" http://localhost:3000/event/error
T 127.0.0.1:44441 -> 127.0.0.1:3000 [AP]
POST /event/error HTTP/1.1.
Authorization: Basic SzM5Mjg6ODc2NXJkZmdoam5idmNkOQ==.
User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3.
Host: localhost:3000.
Accept: */*.
Content-Type: application/data.
Content-Length: 13.
.
Unknown error
I'm considering replacing the middleware with a more liberal one because even though the request is wrong, I'd still like to be able to decide what to do with the body myself. It's a really weird choice to zero the request body when the request doesn't make sense. I actually think a more correct behavior would be to pass it to an error handler which by default would return a 400 Bad Request or 406 Not Acceptable.
Any thoughts on that? In my case I might propose a patch to Compojure.
According to:
http://mmcgrana.github.com/ring/ring.middleware.content-type-api.html
the default content type is application/octet-stream. Unless you actively support that content type, can't you just check if the content type matches that one, and then dump whatever you need based on that?

Resources