Commit b01dd67e32ede69d94ab7c2133b83f30a6e776fc

Authored by Cédric RICARD
1 parent 52a42728

SendMail: added CRAM-MD5 and LOGIN authentication

calexium_lib/mail/authentication.anubis 0 → 100644
  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
... ...