Commit 8a58c06e58a834428310c82ba7870729d9bb2bba
- Diff rendering mode:
- inline
- side by side
.DS_Store
(2 / 2)
Binary files differ
gpg_smtp_server.rb
(1 / 1)
|   | |||
| 244 | 244 | ||
| 245 | 245 | if gpginfo.length == 0 | |
| 246 | 246 | sendmail( rcpArray, encrypted_msg ) | |
| 247 | client.write "250 Ok" + LINESEP | ||
| 247 | client.write "250 OK" + LINESEP | ||
| 248 | 248 | log "mail sent, 250 OK signaled, last line received: " + line | |
| 249 | 249 | else | |
| 250 | 250 | log "encryption error occured!" |
gpgmime.rb
(39 / 18)
|   | |||
| 81 | 81 | # get the range for the complete key-value pair, required to remove key | |
| 82 | 82 | def getKeyStringRange( key, string, sepchar ) | |
| 83 | 83 | keystring = key+sepchar | |
| 84 | if string.match(/^#{keystring}/) == nil | ||
| 84 | if string.match(/^#{keystring}/i) == nil | ||
| 85 | 85 | return | |
| 86 | 86 | end | |
| 87 | start_index = string.index(/^#{keystring}/) | ||
| 87 | start_index = string.index(/^#{keystring}/i) | ||
| 88 | 88 | cont_str = string[start_index, string.length - start_index] | |
| 89 | 89 | line_length = cont_str.index(/\r\n[-a-zA-Z0-9_"]/) + 2 # CRLF has to be removed too | |
| 90 | 90 | [start_index, line_length] | |
| … | … | ||
| 97 | 97 | ||
| 98 | 98 | keystring = key+sepchar | |
| 99 | 99 | ||
| 100 | start_index = string.index(/^#{keystring}/) | ||
| 100 | start_index = string.index(/^#{keystring}/i) | ||
| 101 | 101 | if( start_index != nil ) | |
| 102 | 102 | ||
| 103 | 103 | start_index += keystring.length | |
| … | … | ||
| 157 | 157 | # main key with getValueforKey value first | |
| 158 | 158 | def getValueForSubKey( key, string ) | |
| 159 | 159 | keystring = key+"=" | |
| 160 | /(#{keystring})(.+)(;|#{LINESEP})/m =~ ( string+";" ) | ||
| 160 | /(#{keystring})(.+)(;|#{LINESEP})/mi =~ ( string+";" ) | ||
| 161 | 161 | if Regexp.last_match(2) != nil | |
| 162 | 162 | Regexp.last_match(2).chomp | |
| 163 | 163 | else | |
| … | … | ||
| 169 | 169 | # assigns a value to a given sub key, similar to getValueForSubKey | |
| 170 | 170 | def setValueForSubKey( key, value, string ) | |
| 171 | 171 | keystring = key+"=" | |
| 172 | /(#{keystring})(.+)(;|#{LINESEP})/m =~ ( string+";" ) | ||
| 172 | /(#{keystring})(.+)(;|#{LINESEP})/mi =~ ( string+";" ) | ||
| 173 | 173 | offset = Regexp.last_match.offset(2) | |
| 174 | 174 | value_range = [offset[0], offset[1]-offset[0]] | |
| 175 | 175 | ||
| … | … | ||
| 284 | 284 | # application where we do have only two attachemts which can be distinguished | |
| 285 | 285 | # in this way | |
| 286 | 286 | def getSubContentOfType( type, boundary ) | |
| 287 | if( ( /(Content-Type:)(.*?)(#{type})/ =~ @content_str ) == nil ) | ||
| 287 | if( ( /(Content-Type:)(.*?)(#{type})/i =~ @content_str ) == nil ) | ||
| 288 | 288 | return nil | |
| 289 | 289 | end | |
| 290 | 290 | ||
| … | … | ||
| 292 | 292 | att_end = att_beg + @content_str[ att_beg, @content_str.length - att_beg ].match( boundary ).offset(0)[0] | |
| 293 | 293 | ||
| 294 | 294 | att_str = @content_str[ att_beg, att_end - att_beg] | |
| 295 | |||
| 296 | cont_beg_index = att_str.match(LINESEP+LINESEP).offset(0)[1] | ||
| 295 | |||
| 296 | att_str.match(LINESEP+LINESEP) | ||
| 297 | if Regexp.last_match != nil | ||
| 298 | cont_beg_index = Regexp.last_match.offset(0)[1] | ||
| 299 | else | ||
| 300 | # some GPG/MIME engines unfortunately encrypt obviously with CR instead of CRLF | ||
| 301 | att_str.match("\n\n") | ||
| 302 | if Regexp.last_match != nil | ||
| 303 | cont_beg_index = Regexp.last_match.offset(0)[1] | ||
| 304 | else | ||
| 305 | cont_beg_index = 0 | ||
| 306 | end | ||
| 307 | end | ||
| 308 | |||
| 297 | 309 | att_str[ cont_beg_index, att_str.length - cont_beg_index] | |
| 298 | 310 | end | |
| 299 | 311 | ||
| … | … | ||
| 571 | 571 | ||
| 572 | 572 | # check mime type and get boundary | |
| 573 | 573 | cntType = getContentType() | |
| 574 | |||
| 574 | 575 | if cntType.match("application\/pgp-encrypted") == nil | |
| 575 | 576 | return "input stream with wrong content-type, must be pgp-encrypted!" | |
| 576 | 577 | end | |
| 577 | 578 | boundary = getValueForSubKey( "boundary", cntType ) | |
| 578 | 579 | /(")(.*?)(")/=~boundary | |
| 579 | boundary = "--"+Regexp.last_match(2) | ||
| 580 | boundary = "--"+Regexp.last_match(2) | ||
| 580 | 581 | ||
| 581 | 582 | # check PGP/Mime Version ( normally this is in the first attachment ) | |
| 582 | version_str = getSubContentOfType( "application\/pgp-encrypted", boundary ) | ||
| 583 | version_str = getSubContentOfType( "application\/pgp-encrypted", boundary ) | ||
| 583 | 584 | if version_str==nil || version_str.match("Version: 1") == nil | |
| 584 | 585 | return "only version 1 for application/pgp-encrypted mime type supported!" | |
| 585 | 586 | end | |
| … | … | ||
| 615 | 615 | ||
| 616 | 616 | # exchange content and attach gpg signature info at the end of the message | |
| 617 | 617 | @content_str = decrypted_content + LINESEP | |
| 618 | add_signature( gpgmsg ) | ||
| 619 | |||
| 618 | |||
| 620 | 619 | # deliver gpg error code to invoker if any | |
| 621 | 620 | if gpg_result_code != 0 | |
| 622 | 621 | gpgmsg | |
| 623 | 622 | else | |
| 624 | "" | ||
| 623 | if getContentType().match( "application\/pgp-signature" ) | ||
| 624 | check_clearsig | ||
| 625 | else | ||
| 626 | add_signature( gpgmsg ) | ||
| 627 | "" | ||
| 628 | end | ||
| 625 | 629 | end | |
| 626 | 630 | ||
| 627 | 631 | end | |
| … | … | ||
| 633 | 633 | ||
| 634 | 634 | # checks clear text signature | |
| 635 | 635 | def check_clearsig | |
| 636 | |||
| 636 | 637 | # check mime type and get boundary | |
| 637 | 638 | cntType = getContentType() | |
| 638 | 639 | if cntType.match("application\/pgp-signature") == nil | |
| … | … | ||
| 644 | 644 | boundary = "--"+Regexp.last_match(2) | |
| 645 | 645 | ||
| 646 | 646 | # extract signed content which must be the first section | |
| 647 | if @content_str.match( boundary+LINESEP ) == nil | ||
| 647 | # some email clients unfortunately use CR instead of CRLF before encrpytion | ||
| 648 | if @content_str.match( boundary+LINESEP ) == nil && @content_str.match( boundary+"\n" ) == nil | ||
| 648 | 649 | return "input stream does not provide specified boundaries!" | |
| 649 | 650 | end | |
| 650 | 651 | ||
| 651 | 652 | signed_content = @content_str[Regexp.last_match.offset(0)[1], @content_str.length] | |
| 652 | 653 | ||
| 653 | if signed_content.match( LINESEP+boundary ) == nil | ||
| 654 | if signed_content.match( LINESEP+boundary ) == nil && signed_content.match( "\n"+boundary ) == nil | ||
| 654 | 655 | return "input stream does not provide specified boundaries!" | |
| 655 | 656 | end | |
| 656 | 657 | ||
| 657 | 658 | signed_content = $` | |
| 658 | 659 | ||
| 659 | # extract key | ||
| 660 | # extract key | ||
| 660 | 661 | sig_str = getSubContentOfType( "application\/pgp-signature", boundary ) | |
| 661 | 662 | if( sig_str == nil ) | |
| 662 | 663 | return "missing section application/pgp-signature in input stream!" | |
| … | … | ||
| 671 | 671 | # invoke gpg subprocess | |
| 672 | 672 | dummy, gpgmsg, gpg_result_code = | |
| 673 | 673 | gpg( [], signed_content, "--batch --verify #{sigfilename} -", nil ) | |
| 674 | |||
| 675 | |||
| 674 | |||
| 676 | 675 | # RFC 822 requires originally CRLF, but some mua handle it different | |
| 677 | 676 | # split encrypted content in original header and content information | |
| 678 | 677 | splitmatch = signed_content.match( LINESEP+LINESEP ) | |
| … | … | ||
| 703 | 703 | ||
| 704 | 704 | end | |
| 705 | 705 | ||
| 706 | |||
| 707 | |||
| 706 | 708 | public | |
| 707 | 709 | ||
| 708 | 710 | # invokes depending of content type decrypt or check_clearsig | |
| … | … | ||
| 724 | 724 | return res | |
| 725 | 725 | ||
| 726 | 726 | end | |
| 727 | |||
| 727 | 728 | ||
| 728 | 729 | # delivers an array with all email addresses to public keys | |
| 729 | 730 | def getPubKeyAddressList |

