Commit b01dd67e32ede69d94ab7c2133b83f30a6e776fc
1 parent
52a42728
SendMail: added CRAM-MD5 and LOGIN authentication
Showing
2 changed files
with
201 additions
and
3 deletions
Show diff stats
| 1 | +/* | |
| 2 | + * Created by PyramIDE. | |
| 3 | + * User: ricard | |
| 4 | + * Date: 07/03/2009 | |
| 5 | + * Time: 21:42 | |
| 6 | + * | |
| 7 | + * To change this template use Tools | Options | Coding | Edit Standard Headers. | |
| 8 | + */ | |
| 9 | + | |
| 10 | +read tools/basis.anubis | |
| 11 | +read system/bytearray.anubis | |
| 12 | +read system/string.anubis | |
| 13 | + | |
| 14 | + /** Give a timestamp according to RFC2822. this sort of timestamp | |
| 15 | + * is use for CRAM authentication (Challenge Reponse Authentication Mechanism) | |
| 16 | + * this time timestamp must unique and not predictable to ensure security | |
| 17 | + * mechanism of authentication. | |
| 18 | + * @param dummy One meaning nothing | |
| 19 | + * @return Sring of the timestamp | |
| 20 | + */ | |
| 21 | +public define String | |
| 22 | + get_time_stamp | |
| 23 | + ( | |
| 24 | + String domain | |
| 25 | + )= | |
| 26 | + // TODO V1.X Timestan for CRAM: replace 'smtp.mailfountain.com' by the real server name | |
| 27 | + with time = (UTime) unow, | |
| 28 | + "<"+virtual_machine_id+"."+time.seconds+"@mail."+domain+">". | |
| 29 | + | |
| 30 | + /** | |
| 31 | + */ | |
| 32 | +public define Bool | |
| 33 | + apop_md5 | |
| 34 | + ( | |
| 35 | + String time_stamp, | |
| 36 | + String password, | |
| 37 | + String given_hash | |
| 38 | + ) = | |
| 39 | + with my_stamp = time_stamp + password, | |
| 40 | + my_hash = to_lower(to_ascii(md5(to_byte_array(my_stamp)))), | |
| 41 | +// print("time_stamp "+ time_stamp + "\n"); | |
| 42 | +// print("given_hash " + given_hash + "\n"); | |
| 43 | +// print("my_hash " + my_hash + "\n"); | |
| 44 | + if to_lower(given_hash) = my_hash then | |
| 45 | + true | |
| 46 | + else | |
| 47 | + false. | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | +define String | |
| 52 | + hmac_md5_compute | |
| 53 | + ( | |
| 54 | + ByteArray data, //message to be cripted | |
| 55 | + ByteArray key //this is share secret key (i.e. password) | |
| 56 | + ) = | |
| 57 | + with ba_data = constant_byte_array(64, 0), | |
| 58 | + ba_ipad = constant_byte_array(64, 0x36), | |
| 59 | + ba_opad = constant_byte_array(64, 0x5c), | |
| 60 | + //put key into ByteArray | |
| 61 | + //but if key is longer than 64 bytes, then we must apply md5 on it and put it into ByteArray | |
| 62 | + with ba_key = fill_ByteArray(ba_data, if length(key) > 64 then md5(key) else key), | |
| 63 | + key_ipad = ba_key : ba_ipad, // XOR key with ipad | |
| 64 | + key_opad = ba_key : ba_opad, // XOR key with opad | |
| 65 | + to_lower(to_ascii(md5(key_opad + (md5(key_ipad + data))))). // md5(K (+) ipad) and merge with data | |
| 66 | + | |
| 67 | + | |
| 68 | +define Bool | |
| 69 | + hmac_md5_check | |
| 70 | + ( | |
| 71 | + ByteArray data, //message to be cripted | |
| 72 | + ByteArray key, //this is share secret key (i.e. password) | |
| 73 | + String given_digest //The hash given by the user who want to be authenticated | |
| 74 | + ) = | |
| 75 | + if to_lower(given_digest) = hmac_md5_compute(data, key) then | |
| 76 | +// print("HMAC-MD5 Success \n"); | |
| 77 | + true | |
| 78 | + else | |
| 79 | +// print("HMAC-MD5 Failed \n"); | |
| 80 | +// print(" My Hash = " + my_hash + "\n"); | |
| 81 | +// print("User Hash = " + given_digest + "\n"); | |
| 82 | + false. | |
| 83 | + | |
| 84 | +public define Bool | |
| 85 | + hmac_md5_check | |
| 86 | + ( | |
| 87 | + String data, //message to be cripted | |
| 88 | + String key, //this is share secret key (i.e. password) | |
| 89 | + String given_digest //The hash given by the user who want to be authenticated | |
| 90 | + ) = | |
| 91 | + hmac_md5_check(to_byte_array(data), to_byte_array(key), given_digest). | |
| 92 | + | |
| 93 | +public define String | |
| 94 | + hmac_md5_compute | |
| 95 | + ( | |
| 96 | + String data, //message to be cripted | |
| 97 | + String key //this is share secret key (i.e. password) | |
| 98 | + ) = | |
| 99 | + hmac_md5_compute(to_byte_array(data), to_byte_array(key)). | ... | ... |
calexium_lib/mail/send_mail.anubis
| ... | ... | @@ -23,6 +23,7 @@ read calexium_lib/net_services_protocols/logger_service.anubis |
| 23 | 23 | |
| 24 | 24 | read lexers/enhanced_status.anubis |
| 25 | 25 | read smtp_server_extensions.anubis |
| 26 | +read authentication.anubis | |
| 26 | 27 | |
| 27 | 28 | public define String send_mail_log = "SendMail". |
| 28 | 29 | public define LogMask send_mail_mask = logMask("send_mail"). |
| ... | ... | @@ -585,6 +586,100 @@ define SendMailResult |
| 585 | 586 | reply_handling(code,lines,enhanced_status) |
| 586 | 587 | } |
| 587 | 588 | }. |
| 589 | + | |
| 590 | +define SendMailResult | |
| 591 | + do_auth_login | |
| 592 | + ( | |
| 593 | + RWStream conn, | |
| 594 | + String login, | |
| 595 | + String password, | |
| 596 | + Bool enhanced_status, | |
| 597 | + (LogLevel, String) -> One logger | |
| 598 | + )= | |
| 599 | + if smtp_send_line(conn, "AUTH LOGIN", logger) is | |
| 600 | + { | |
| 601 | + failure then error, // already logged | |
| 602 | + success(_) then | |
| 603 | + if receive_reply(conn, logger) is | |
| 604 | + { | |
| 605 | + error then error // already logged | |
| 606 | + timeout then error, | |
| 607 | + reply(code, lines) then | |
| 608 | + if code = 334 then | |
| 609 | + if smtp_send_line(conn, to_string(base64_encode(to_byte_array(login))), logger) is | |
| 610 | + { | |
| 611 | + failure then error, // already logged | |
| 612 | + success(_) then | |
| 613 | + if receive_reply(conn, logger) is | |
| 614 | + { | |
| 615 | + error then error // already logged | |
| 616 | + timeout then error, | |
| 617 | + reply(code_login, lines_login) then | |
| 618 | + if code = 334 then | |
| 619 | + if smtp_send_line(conn, to_string(base64_encode(to_byte_array(password))), logger) is | |
| 620 | + { | |
| 621 | + failure then error, // already logged | |
| 622 | + success(_) then | |
| 623 | + if receive_reply(conn, logger) is | |
| 624 | + { | |
| 625 | + error then error // already logged | |
| 626 | + timeout then error, | |
| 627 | + reply(code_pwd, lines_pwd) then | |
| 628 | + if code = 235 then | |
| 629 | + ok | |
| 630 | + else | |
| 631 | + reply_handling(code_pwd, lines_pwd, enhanced_status) | |
| 632 | + } | |
| 633 | + } | |
| 634 | + else | |
| 635 | + reply_handling(code_login, lines_login, enhanced_status) | |
| 636 | + } | |
| 637 | + } | |
| 638 | + else | |
| 639 | + reply_handling(code, lines, enhanced_status) | |
| 640 | + } | |
| 641 | + }. | |
| 642 | + | |
| 643 | +define SendMailResult | |
| 644 | + do_auth_cram_md5 | |
| 645 | + ( | |
| 646 | + RWStream conn, | |
| 647 | + String login, | |
| 648 | + String password, | |
| 649 | + Bool enhanced_status, | |
| 650 | + (LogLevel, String) -> One logger | |
| 651 | + )= | |
| 652 | + if smtp_send_line(conn, "AUTH CRAM-MD5", logger) is | |
| 653 | + { | |
| 654 | + failure then error, // already logged | |
| 655 | + success(_) then | |
| 656 | + if receive_reply(conn, logger) is | |
| 657 | + { | |
| 658 | + error then error // already logged | |
| 659 | + timeout then error, | |
| 660 | + reply(code, lines) then | |
| 661 | + if code = 334 then | |
| 662 | + with challenge = if lines is [h . t] then base64_decode(h) else "", | |
| 663 | + digest = hmac_md5_compute(challenge, password), | |
| 664 | + if smtp_send_line(conn, base64_encode(login + " " + digest, false), logger) is | |
| 665 | + { | |
| 666 | + failure then error, // already logged | |
| 667 | + success(_) then | |
| 668 | + if receive_reply(conn, logger) is | |
| 669 | + { | |
| 670 | + error then error // already logged | |
| 671 | + timeout then error, | |
| 672 | + reply(code_login, lines_login) then | |
| 673 | + if code = 235 then | |
| 674 | + ok | |
| 675 | + else | |
| 676 | + reply_handling(code_login, lines_login, enhanced_status) | |
| 677 | + } | |
| 678 | + } | |
| 679 | + else | |
| 680 | + reply_handling(code, lines, enhanced_status) | |
| 681 | + } | |
| 682 | + }. | |
| 588 | 683 | |
| 589 | 684 | define SendMailResult |
| 590 | 685 | do_login |
| ... | ... | @@ -596,11 +691,15 @@ define SendMailResult |
| 596 | 691 | Bool enhanced_status, |
| 597 | 692 | (LogLevel, String) -> One logger |
| 598 | 693 | )= |
| 599 | - | |
| 600 | - if member(auth_list, "PLAIN", insensitive_equal) then | |
| 694 | + if member(auth_list, "CRAM-MD5", insensitive_equal) then | |
| 695 | + do_auth_cram_md5(conn, login, password, enhanced_status, logger) | |
| 696 | + else if member(auth_list, "PLAIN", insensitive_equal) then | |
| 601 | 697 | do_auth_plain(conn, login, password, enhanced_status, logger) |
| 698 | + else if member(auth_list, "LOGIN", insensitive_equal) then | |
| 699 | + do_auth_login(conn, login, password, enhanced_status, logger) | |
| 700 | + | |
| 602 | 701 | else |
| 603 | - logger(logError, "do_login no PLAIN method available"); error. | |
| 702 | + logger(logError, "do_login: none of CRAM-MD5, LOGIN or PLAIN method available"); error. | |
| 604 | 703 | |
| 605 | 704 | define SendMailResult |
| 606 | 705 | do_auth | ... | ... |