[Incidencias #2782] S/MIME Sign using browser capabilities

bugs@bugs.horde.org bugs at bugs.horde.org
Wed Aug 23 04:12:19 PDT 2006


NO CONTESTE A ESTE MENSAJE. ESTA DIRECCIÓN NO ESTÁ REVISADA.

URL de la incidencia: http://bugs.horde.org/ticket/?id=2782
-----------------------------------------------------------------------
 Incidencia         | 2782
 Actualizado por    | mfernandez at gva.es
 Resumen            | S/MIME Sign using browser capabilities
 Cola               | IMP
 Versión            | HEAD
 Tipo               | Enhancement
 Estado             | Feedback
 Prioridad          | 1. Low
 Propietarios       | Horde Developers, Michael Slusarz
+New Attachment     | form-resubmit-1.patch
-----------------------------------------------------------------------


mfernandez at gva.es (2006-08-23 04:12) escribió:

>> Wouldn't you consider the AJAX alternative?
> Of course, but why would the help with the splitting of message 
> building and sending?
>> I could send you the changes so far as patched.
> Sure, talking about some real code is always easier.
I don't know if you are interested in code details.
So I prepared a Brief and an Extended version,
both for AJAX and Without AJAX.
The extended version helps me to organize myself 
(and also document these changes).
Here is the flow control of composing, singning and sending a message 
the way I know today.

Without AJAX:
~~~~~~~~~~~~~
Brief:
------
1) Submit the form as usual.
2) Build a text/plain MIME for each recipient.
3) Marshall return values as form hidden inputs.
4) Render the compose page again.
5) Hook on onload event to sign text/plain MIMES.
6) ReSubmit this form.
7) Unmarshall submitted form hidden inputs to carry on.
8) Build a multipart/signed for each pair of (text/plain, signature)
9) Now send all as usual.

Extended:
---------
1) Send the form.

The page is loaded, the compose form is fulfilled, and submitted 
with actionID="send-message'.

2) Build a text/plain MIME for each recipient.

/imp/compose.php is called, the following code is executed

case 'send_message':
...
$imp_compose->buildAndSendMessage(...);

My goal is to split this function in two, because I need to sing
in the browser between "build" and "send". 
Right now, the patch I sent "composed" the text/plain part of the MIME 
in a Javascript function. 
I should leave that to the "build" part of this function. 
So, I need 2 new functions:
/imp/lib/Compose.php::buildMessage()
/imp/lib/Compose.php::sendMessage()
The original buildAndSendMessage() is kept for backwards compatibility 
and calls these two new ones. 
I have done this refactoring and the coupling between these is strong. 
Many parameters and array of return values.

    function buildAndSendMessage(<original parameters>)
    {
        list($messagesToSend, $recipients, $messageToSave) = 
                        $this->buildMessage(<original parameters>);
        /** 
         * Vars in the list() is the coupling between buildMessage() 
         * and sendMessage()
         */ 
        $sent_saved = $this->sendMessages($messagesToSend, $recipients, 
                                 $messageToSave, <original parameters>);
        return $sent_saved;
    }

Besides, buildMessage() does some work if there are multiple recipients 
when signing, so <signing flag> so say "true":

    if (<signing flag>) {
        /* Must encrypt & send the message one recipient at a time. */
        foreach ($recipientArray as $val) {
            $res = $this->_createMimeMessage(array($val), $body,
$encrypt);
            ...
        }
        ...
    }

Here, buildMessage() calls _createMimeMessage(), one for each recipient.
_createMimeMessage() is exactly the piece of code I want to replace the 
Javascript with. However, this function also encrypts, wich I don't need
right 
now since encryption is carried out later on the browser. 
I just want it to compose the text/plain part.

    function _createMimeMessage($to, $body, $encrypt)
    {
        ...
        <mostly encryption code>
        ...
        /* Add data to MIME_Message object. */
        $mime_message->addPart($body);\
        ...
        return array('recipients' => $to,
                     'to' => implode(', ', $to),
                     'msg' => &$mime_message);
    }        

3) Marshall return values as form hidden inputs.

When all this calls return, I have to break the switch statement at 
/imp/compose.php.

Right here I have an array of 3 values returned from buildMessage();


    function buildMessage(...)
    {
        ...
        return array($messagesToSend, $recipients, $messageToSave);
    }

    list($messagesToSend, $recipients, $messageToSave) = buildMessage();

In the original normal flow of actionID='send_message' these 3 values 
are needed by the following lines of code of this switch case. 
But now, I must break the flow and show the compose form again 
with these 3 values rendered in the form as hidden inputs. 
This task is not pretty. For example, $messagesToSend is an array of 3
objects,
one of them is an IMP_MIME wich I have to transform toCanonicalString().
I have not completed this marshalling yet, $recipients and $messageToSave
are missing. Here is a bit of code from /imp/compose.php:

    /* Prepare the messages in the form to be signed in browser */
    if (isset($messagesToSend)) {
        $canonical_mimes = array();
        foreach ($messagesToSend as $mime_message )
            $canonical_mimes[] =
$mime_message['msg']->toCanonicalString();
        $t->set('messagesToSend', $canonical_mimes);
    }

4) Render the compose page again.

This is done in /imp/templates/compose/compose.html:

<!-- These are the MIMEs to be signed -->
<loop:messagesToSend>
<input type="hidden" name="messagesToSend" value="<tag:messagesToSend />"
/>
</loop:messagesToSend>

Wich should write some hmtl code like this:

<input type="hidden" name="messagesToSend" value="Content-type: text/plain
..." />
<input type="hidden" name="messagesToSend" value="Content-type: text/plain
..." />
<input type="hidden" name="recipients" value="..." />
<input type="hidden" name="messageToSave" value="..." />

I am missing all code from here. It is not in the patch I attached just
now.
5) Hook on onload event to sign text/plain MIMES.

With all of this values on the form, I have to hook page onload event 
to fire the javascript that takes the text/plain messagesToSend and signs
them.

6) ReSubmit this form.

7) Unmarshall submitted form hidden inputs to carry on.

The switch structure on /imp/compose.php now looks like this:

case 'send_message':
case 'compose_mime':
    ...
    if ($actionID == 'compose_mime') {
        $marshall_all_this = $imp_compose->buildMessage(...);
        break;
    }

case 'send_mime':

    if ($actionID == 'send_mime') {
        /* We are coming from a form submit */
        $unmarshalled_values =
not_implemented_yet(<Util::getFormData()>);
        $sent = $imp_compose->sendMessages($unmarshalled_values);
    } else {
        /* The switch case did not break, so al usual variables are
available */
        $sent = $imp_compose->buildAndSendMessage(<usual parameters>);
    }

8) Build a multipart/signed for each pair of (text/plain, signature)

Here's another problem, since now I would need to call buildMessage()
again, 
so a multipart/signed is composed with every signed text/plain. 
Remember, we already called it to compose the text/plain. 

9) Now send all as usual.

With the multipart/signed already composed, now I can send the messages 
calling the refactored sendMessages(). 
But before I have to re-construct the parameters we stored as hiddens 
in the form to pass them to this functions. Another not pretty task.

If all this succeeds, the messages are sent as multipart/signed.

The AJAX way:
~~~~~~~~~~~~~
Introduction:
-------------
I have written no code at all at this time. I have little experience
with AJAX, so maybe some of this can't be done the way I wished.
This approach should mean very little PHP code changes, plus a better
user experience. I am going to need much advise on how to embed Ajax
in the PHP templates, if this strategy is finally accepted.
 
Brief:
------
1) Fire the javascript signing function on form submit.
2) Call imp/lib/Compose.php::IMP_Compose::_createMimeMessage($to, $body,
$encrypt)
   via Ajax to compose text/plain MIME(s if multiple recipients).
3) Sign the text/plain part returned by the Ajax call.
4) Set the signature(s if multiple recipients) as hidden inputs.
5) Submit this form with actionID='send_message'.

Extended:
---------

1) Fire the javascript signing function on form submit.

This change is already in the first patch. uniqSubmit() function
calls signMessage() if singning has been requested by selecting it
in the drop-down list.

2) Call imp/lib/Compose.php::IMP_Compose::_createMimeMessage($to, $body,
$encrypt)
   via Ajax to compose text/plain MIME(s if multiple recipients).
   
To sign the message we need the message itself as a text/plain MIME.
This is provided by the PHP server side by wrapping the call to
class IMP_Compose. We need to expose _createMimeMessage() method to
return
one or multiple text/plain MIMEs depending on how many recipients there
are.

3) Sign the text/plain part returned by the Ajax call.
& 4) Set the signature(s if multiple recipients) as hidden inputs.

I sign each text/plain part we retrieved by AJAX, storing each
signature as a form hidden input.
 
5) Submit this form with actionID='send_message'.

Just go on and submit the form as usual.
Do not encrypt when buildAndSendMessage() calls _createMimeMessage(), 
just compose the multipart/signed with the signature provided.
This change is already on the first patch (how do you reference different
patches so not to bring confusion, do you number/timestamp them?).

Feel free to correct my English. In fact, I would appreciate it.

Thanks,

Mariano.





More information about the bugs mailing list