{"thread":{"id":"26190","subject":"[RFC][PATCH] git-send-email: added support for S/MIME","startedAt":"2011-01-04T16:02:06Z","lastAt":"2011-01-05T09:22:02Z","messageCount":4,"participants":["Roberto Sassu","Junio C Hamano","Thomas Rast"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"158895","messageId":"1294156930-21367-1-git-send-email-roberto.sassu@polito.it","threadId":"26190","inReplyTo":null,"subject":"[RFC][PATCH] git-send-email: added support for S/MIME","fromName":"Roberto Sassu","fromEmail":"roberto.sassu@polito.it","sentAt":"2011-01-04T16:02:06Z","receivedAt":"2011-01-04T16:02:06Z","isPatch":true,"sender":{"key":"roberto.sassu@polito.it","avatar":null},"body":"The script git-send-email.perl has been modified in order to add support\nfor messages with S/MIME format.  First, the message body is written in a\ntemporary file and signed by OpenSSL with the X.509 certificate provided by\nthe user.  Then the returned content is added to the previously parsed\nheader and the message is sent as the same for unsigned messages.\n\nUsage:\n    git send-email -sign -signing-cert </path/of/PEM> <other options>\n\nSigned-off-by: Roberto Sassu <roberto.sassu@polito.it>\n---\n git-send-email.perl |   97 +++++++++++++++++++++++++++++++++++++++++++++-----\n 1 files changed, 87 insertions(+), 10 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 76565de..c040fe6 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -57,6 +57,8 @@ git send-email [options] <file | directory | rev-list options >\n     --annotate                     * Review each patch that will be sent in an editor.\n     --compose                      * Open an editor for introduction.\n     --8bit-encoding         <str>  * Encoding to assume 8bit mails if undeclared\n+    --sign                         * Sign all emails with an X.509 certificate.\n+    --signing-cert          <str>  * Path of the X.509 certificate.\n \n   Sending:\n     --envelope-sender       <str>  * Email envelope sender.\n@@ -141,7 +143,7 @@ my $auth;\n \n # Variables we fill in automatically, or via prompting:\n my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,\n-\t$initial_reply_to,$initial_subject,@files,\n+\t@xb,$initial_reply_to,$initial_subject,@files,\n \t$author,$sender,$smtp_authpass,$annotate,$compose,$time);\n \n my $envelope_sender;\n@@ -161,9 +163,10 @@ if ($@) {\n }\n \n # Behavior modification variables\n-my ($quiet, $dry_run) = (0, 0);\n+my ($quiet, $dry_run, $sign) = (0, 0, 0);\n my $format_patch;\n my $compose_filename;\n+my $signing_cert;\n my $force = 0;\n \n # Handle interactive edition of files.\n@@ -232,6 +235,7 @@ my %config_settings = (\n     \"confirm\"   => \\$confirm,\n     \"from\" => \\$sender,\n     \"assume8bitencoding\" => \\$auto_8bit_encoding,\n+    \"signing_cert\" => \\$signing_cert\n );\n \n # Help users prepare for 1.7.0\n@@ -311,6 +315,8 @@ my $rc = GetOptions(\"sender|from=s\" => \\$sender,\n \t\t    \"format-patch!\" => \\$format_patch,\n \t\t    \"8bit-encoding=s\" => \\$auto_8bit_encoding,\n \t\t    \"force\" => \\$force,\n+\t\t    \"sign\" => \\$sign,\n+\t\t    \"signing-cert:s\" => \\$signing_cert,\n \t );\n \n unless ($rc) {\n@@ -356,6 +362,11 @@ sub read_config {\n \t}\n }\n \n+# verify if the signing certificate has been specified\n+if ($sign && !$signing_cert) {\n+\tdie \"Signing certificate not specified\";\n+}\n+\n # read configuration from [sendemail \"$identity\"], fall back on [sendemail]\n $identity = Git::config(@repo, \"sendemail.identity\") unless (defined $identity);\n read_config(\"sendemail.$identity\") if (defined $identity);\n@@ -1161,6 +1172,7 @@ foreach my $t (@files) {\n \t@to = ();\n \t@cc = ();\n \t@xh = ();\n+\t@xb = ();\n \tmy $input_format = undef;\n \tmy @header = ();\n \t$message = \"\";\n@@ -1223,7 +1235,20 @@ foreach my $t (@files) {\n \t\t\t\tif (/charset=\"?([^ \"]+)/) {\n \t\t\t\t\t$body_encoding = $1;\n \t\t\t\t}\n-\t\t\t\tpush @xh, $_;\n+\t\t\t\tif ($sign) {\n+\t\t\t\t\tpush @xb, $_;\n+\t\t\t\t} else {\n+\t\t\t\t\tpush @xh, $_;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\telsif (/^MIME-Version:/i && $sign) {\n+\t\t\t\t# Do nothing: this will be added by OpenSSL\n+\t\t\t}\n+\t\t\telsif (/Content-Transfer-Encoding:/i && $sign) {\n+\t\t\t\t# move the Content-Transfer-Encoding in the\n+\t\t\t\t# first part of the message if the latter is\n+\t\t\t\t# about to be signed\n+\t\t\t\tpush @xb, $_;\n \t\t\t}\n \t\t\telsif (/^Message-Id: (.*)/i) {\n \t\t\t\t$message_id = $1;\n@@ -1275,9 +1300,14 @@ foreach my $t (@files) {\n \n \tif ($broken_encoding{$t} && !$has_content_type) {\n \t\t$has_content_type = 1;\n-\t\tpush @xh, \"MIME-Version: 1.0\",\n-\t\t\t\"Content-Type: text/plain; charset=$auto_8bit_encoding\",\n-\t\t\t\"Content-Transfer-Encoding: 8bit\";\n+\t\tif ($sign) {\n+\t\t\tpush @xb, \"Content-Type: text/plain; charset=$auto_8bit_encoding\",\n+\t\t\t\t  \"Content-Transfer-Encoding: 8bit\";\n+\t\t} else {\n+\t\t\tpush @xh, \"MIME-Version: 1.0\",\n+\t\t\t\t\"Content-Type: text/plain; charset=$auto_8bit_encoding\",\n+\t\t\t\t\"Content-Transfer-Encoding: 8bit\";\n+\t\t}\n \t\t$body_encoding = $auto_8bit_encoding;\n \t}\n \n@@ -1298,12 +1328,59 @@ foreach my $t (@files) {\n \t\t\t}\n \t\t\telse {\n \t\t\t\t$has_content_type = 1;\n-\t\t\t\tpush @xh,\n-\t\t\t\t  'MIME-Version: 1.0',\n-\t\t\t\t  \"Content-Type: text/plain; charset=$author_encoding\",\n-\t\t\t\t  'Content-Transfer-Encoding: 8bit';\n+\t\t\t\tif ($sign) {\n+\t\t\t\t\tpush @xb,\n+\t\t\t\t\t  \"Content-Type: text/plain; charset=$author_encoding\",\n+\t\t\t\t\t  'Content-Transfer-Encoding: 8bit';\n+\t\t\t\t} else {\n+\t\t\t\t\tpush @xh,\n+\t\t\t\t\t  'MIME-Version: 1.0',\n+\t\t\t\t\t  \"Content-Type: text/plain; charset=$author_encoding\",\n+\t\t\t\t\t  'Content-Transfer-Encoding: 8bit';\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif ($sign) {\n+ \t\tmy $linecount = 0;\n+\t\tmy $message_body_tmp_file;\n+\n+\t\t# put the original Content-Type, charset and Content-Transfer-Encoding\n+\t\t# information, if specified, in the first part of the message\n+\t\tif (@xb) {\n+\t\t\t$message = join(\"\\n\", @xb) . \"\\n\\n\" . $message;\n+\t\t} else {\n+\t\t\t$message = \"\\n\" . $message;\n+\t\t}\n+\n+\t\t# write the message body in a temporary file\n+\t\t$message_body_tmp_file = ($repo ?\n+\t\t\ttempfile(\".gitsendemail.body.XXXXXX\", DIR => $repo->repo_path()) :\n+\t\t\ttempfile(\".gitsendemail.body.XXXXXX\", DIR => \".\"))[1];\n+\n+\t\topen(MESSAGE_BODY_FILE,\">\",$message_body_tmp_file) or\n+\t\t\tdie \"Failed to open for writing $message_body_tmp_file: $!\";\n+\t\tprint MESSAGE_BODY_FILE $message;\n+\t\tclose MESSAGE_BODY_FILE;\n+\n+\t\t# sign the message body and put the result in the $message variable\n+\t\t$message = \"\";\n+\t\topen(OPENSSL_SIGNED_MESSAGE, \"openssl smime -sign -in $message_body_tmp_file -signer $signing_cert |\")\n+\t\t\tor die \"Could not execute OpenSSL\";\n+\n+\t\twhile(<OPENSSL_SIGNED_MESSAGE>) {\n+\t\t\tchomp;\n+\t\t\tif($linecount < 2) {\n+\t\t\t\t# push first two lines into the header\n+\t\t\t\tpush @xh, $_;\n+\t\t\t} else {\n+\t\t\t\t# put the remaining content in the $message variable\n+\t\t\t\t$message .= $_;\n \t\t\t}\n \t\t}\n+\t\tclose OPENSSL_SIGNED_MESSAGE;\n+ \t\tunlink($message_body_tmp_file);\n \t}\n \n \t$needs_confirm = (\n-- \n1.7.3.4\n\n"},{"id":"158909","messageId":"7v1v4sfp8j.fsf@alter.siamese.dyndns.org","threadId":"26190","inReplyTo":"1294156930-21367-1-git-send-email-roberto.sassu@polito.it","subject":"Re: [RFC][PATCH] git-send-email: added support for S/MIME","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-04T19:22:36Z","receivedAt":"2011-01-04T19:22:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Roberto Sassu <roberto.sassu@polito.it> writes:\n\n> ...\n> Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>\n\nThe patch with so many \"if ($sign) do this else do that\" is too ugly\nbeyond words.  I wonder if the surrounding code can be better\nrestructured.\n"},{"id":"158911","messageId":"201101042036.36208.trast@student.ethz.ch","threadId":"26190","inReplyTo":"1294156930-21367-1-git-send-email-roberto.sassu@polito.it","subject":"Re: [RFC][PATCH] git-send-email: added support for S/MIME","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2011-01-04T19:36:36Z","receivedAt":"2011-01-04T19:36:36Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Roberto Sassu wrote:\n> The script git-send-email.perl has been modified in order to add support\n> for messages with S/MIME format.\n\nDoes git-am need symmetric support to decode the message?\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"158954","messageId":"201101051022.02854.roberto.sassu@polito.it","threadId":"26190","inReplyTo":"201101042036.36208.trast@student.ethz.ch","subject":"Re: [RFC][PATCH] git-send-email: added support for S/MIME","fromName":"Roberto Sassu","fromEmail":"roberto.sassu@polito.it","sentAt":"2011-01-05T09:22:02Z","receivedAt":"2011-01-05T09:22:02Z","isPatch":true,"sender":{"key":"roberto.sassu@polito.it","avatar":null},"body":"Hi Thomas\n\nOn Tuesday, January 04, 2011 08:36:36 pm Thomas Rast wrote:\n> Roberto Sassu wrote:\n> > The script git-send-email.perl has been modified in order to add support\n> > for messages with S/MIME format.\n> \n> Does git-am need symmetric support to decode the message?\n\nI think git-am does not require any modification on the code,\nbecause it already supports emails with Content-Type\n'multipart'. One example comes from git-format-patch which\ncan generate patches with this format by adding the option\n'--attach'.\n\nRegards\n\nRoberto Sassu\n"}]}