From b01dd67e32ede69d94ab7c2133b83f30a6e776fc Mon Sep 17 00:00:00 2001 From: Cedric RICARD Date: Sat, 7 Mar 2009 21:57:03 +0000 Subject: [PATCH] SendMail: added CRAM-MD5 and LOGIN authentication --- calexium_lib/mail/authentication.anubis | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ calexium_lib/mail/send_mail.anubis | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 calexium_lib/mail/authentication.anubis diff --git a/calexium_lib/mail/authentication.anubis b/calexium_lib/mail/authentication.anubis new file mode 100644 index 0000000..6fdb132 --- /dev/null +++ b/calexium_lib/mail/authentication.anubis @@ -0,0 +1,99 @@ +/* + * Created by PyramIDE. + * User: ricard + * Date: 07/03/2009 + * Time: 21:42 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +read tools/basis.anubis +read system/bytearray.anubis +read system/string.anubis + + /** Give a timestamp according to RFC2822. this sort of timestamp + * is use for CRAM authentication (Challenge Reponse Authentication Mechanism) + * this time timestamp must unique and not predictable to ensure security + * mechanism of authentication. + * @param dummy One meaning nothing + * @return Sring of the timestamp + */ +public define String + get_time_stamp + ( + String domain + )= + // TODO V1.X Timestan for CRAM: replace 'smtp.mailfountain.com' by the real server name + with time = (UTime) unow, + "<"+virtual_machine_id+"."+time.seconds+"@mail."+domain+">". + + /** + */ +public define Bool + apop_md5 + ( + String time_stamp, + String password, + String given_hash + ) = + with my_stamp = time_stamp + password, + my_hash = to_lower(to_ascii(md5(to_byte_array(my_stamp)))), +// print("time_stamp "+ time_stamp + "\n"); +// print("given_hash " + given_hash + "\n"); +// print("my_hash " + my_hash + "\n"); + if to_lower(given_hash) = my_hash then + true + else + false. + + + +define String + hmac_md5_compute + ( + ByteArray data, //message to be cripted + ByteArray key //this is share secret key (i.e. password) + ) = + with ba_data = constant_byte_array(64, 0), + ba_ipad = constant_byte_array(64, 0x36), + ba_opad = constant_byte_array(64, 0x5c), + //put key into ByteArray + //but if key is longer than 64 bytes, then we must apply md5 on it and put it into ByteArray + with ba_key = fill_ByteArray(ba_data, if length(key) > 64 then md5(key) else key), + key_ipad = ba_key : ba_ipad, // XOR key with ipad + key_opad = ba_key : ba_opad, // XOR key with opad + to_lower(to_ascii(md5(key_opad + (md5(key_ipad + data))))). // md5(K (+) ipad) and merge with data + + +define Bool + hmac_md5_check + ( + ByteArray data, //message to be cripted + ByteArray key, //this is share secret key (i.e. password) + String given_digest //The hash given by the user who want to be authenticated + ) = + if to_lower(given_digest) = hmac_md5_compute(data, key) then +// print("HMAC-MD5 Success \n"); + true + else +// print("HMAC-MD5 Failed \n"); +// print(" My Hash = " + my_hash + "\n"); +// print("User Hash = " + given_digest + "\n"); + false. + +public define Bool + hmac_md5_check + ( + String data, //message to be cripted + String key, //this is share secret key (i.e. password) + String given_digest //The hash given by the user who want to be authenticated + ) = + hmac_md5_check(to_byte_array(data), to_byte_array(key), given_digest). + +public define String + hmac_md5_compute + ( + String data, //message to be cripted + String key //this is share secret key (i.e. password) + ) = + hmac_md5_compute(to_byte_array(data), to_byte_array(key)). diff --git a/calexium_lib/mail/send_mail.anubis b/calexium_lib/mail/send_mail.anubis index c4494d2..d74f5e4 100644 --- a/calexium_lib/mail/send_mail.anubis +++ b/calexium_lib/mail/send_mail.anubis @@ -23,6 +23,7 @@ read calexium_lib/net_services_protocols/logger_service.anubis read lexers/enhanced_status.anubis read smtp_server_extensions.anubis +read authentication.anubis public define String send_mail_log = "SendMail". public define LogMask send_mail_mask = logMask("send_mail"). @@ -585,6 +586,100 @@ define SendMailResult reply_handling(code,lines,enhanced_status) } }. + +define SendMailResult + do_auth_login + ( + RWStream conn, + String login, + String password, + Bool enhanced_status, + (LogLevel, String) -> One logger + )= + if smtp_send_line(conn, "AUTH LOGIN", logger) is + { + failure then error, // already logged + success(_) then + if receive_reply(conn, logger) is + { + error then error // already logged + timeout then error, + reply(code, lines) then + if code = 334 then + if smtp_send_line(conn, to_string(base64_encode(to_byte_array(login))), logger) is + { + failure then error, // already logged + success(_) then + if receive_reply(conn, logger) is + { + error then error // already logged + timeout then error, + reply(code_login, lines_login) then + if code = 334 then + if smtp_send_line(conn, to_string(base64_encode(to_byte_array(password))), logger) is + { + failure then error, // already logged + success(_) then + if receive_reply(conn, logger) is + { + error then error // already logged + timeout then error, + reply(code_pwd, lines_pwd) then + if code = 235 then + ok + else + reply_handling(code_pwd, lines_pwd, enhanced_status) + } + } + else + reply_handling(code_login, lines_login, enhanced_status) + } + } + else + reply_handling(code, lines, enhanced_status) + } + }. + +define SendMailResult + do_auth_cram_md5 + ( + RWStream conn, + String login, + String password, + Bool enhanced_status, + (LogLevel, String) -> One logger + )= + if smtp_send_line(conn, "AUTH CRAM-MD5", logger) is + { + failure then error, // already logged + success(_) then + if receive_reply(conn, logger) is + { + error then error // already logged + timeout then error, + reply(code, lines) then + if code = 334 then + with challenge = if lines is [h . t] then base64_decode(h) else "", + digest = hmac_md5_compute(challenge, password), + if smtp_send_line(conn, base64_encode(login + " " + digest, false), logger) is + { + failure then error, // already logged + success(_) then + if receive_reply(conn, logger) is + { + error then error // already logged + timeout then error, + reply(code_login, lines_login) then + if code = 235 then + ok + else + reply_handling(code_login, lines_login, enhanced_status) + } + } + else + reply_handling(code, lines, enhanced_status) + } + }. define SendMailResult do_login @@ -596,11 +691,15 @@ define SendMailResult Bool enhanced_status, (LogLevel, String) -> One logger )= - - if member(auth_list, "PLAIN", insensitive_equal) then + if member(auth_list, "CRAM-MD5", insensitive_equal) then + do_auth_cram_md5(conn, login, password, enhanced_status, logger) + else if member(auth_list, "PLAIN", insensitive_equal) then do_auth_plain(conn, login, password, enhanced_status, logger) + else if member(auth_list, "LOGIN", insensitive_equal) then + do_auth_login(conn, login, password, enhanced_status, logger) + else - logger(logError, "do_login no PLAIN method available"); error. + logger(logError, "do_login: none of CRAM-MD5, LOGIN or PLAIN method available"); error. define SendMailResult do_auth -- libgit2 0.21.4