Skip to content
Snippets Groups Projects
Commit 111905d6 authored by Rye Mutt's avatar Rye Mutt :bread:
Browse files

Remove dead llmail code

parent 388edb3d
No related branches found
No related tags found
No related merge requests found
......@@ -54,7 +54,6 @@ set(llmessage_SOURCE_FILES
lliopipe.cpp
lliosocket.cpp
llioutil.cpp
llmail.cpp
llmessagebuilder.cpp
llmessageconfig.cpp
llmessagereader.cpp
......@@ -141,7 +140,6 @@ set(llmessage_HEADER_FILES
lliosocket.h
llioutil.h
llloginflags.h
llmail.h
llmessagebuilder.h
llmessageconfig.h
llmessagereader.h
......
/**
* @file llmail.cpp
* @brief smtp helper functions.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmail.h"
// APR on Windows needs full windows headers
#include "llwin32headerslean.h"
#include <string>
#include <sstream>
#include "apr_pools.h"
#include "apr_network_io.h"
#include "llapr.h"
#include "llbase32.h" // IM-to-email address
#include "llblowfishcipher.h"
#include "llerror.h"
#include "llhost.h"
#include "llsd.h"
#include "llstring.h"
#include "lluuid.h"
#include "net.h"
//
// constants
//
const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096;
static bool gMailEnabled = true;
static apr_pool_t* gMailPool;
static apr_sockaddr_t* gSockAddr;
static apr_socket_t* gMailSocket;
bool connect_smtp();
void disconnect_smtp();
//#if LL_WINDOWS
//SOCKADDR_IN gMailDstAddr, gMailSrcAddr, gMailLclAddr;
//#else
//struct sockaddr_in gMailDstAddr, gMailSrcAddr, gMailLclAddr;
//#endif
// Define this for a super-spammy mail mode.
//#define LL_LOG_ENTIRE_MAIL_MESSAGE_ON_SEND 1
bool connect_smtp()
{
// Prepare an soket to talk smtp
apr_status_t status;
status = apr_socket_create(
&gMailSocket,
gSockAddr->sa.sin.sin_family,
SOCK_STREAM,
APR_PROTO_TCP,
gMailPool);
if(ll_apr_warn_status(status)) return false;
status = apr_socket_connect(gMailSocket, gSockAddr);
if(ll_apr_warn_status(status))
{
status = apr_socket_close(gMailSocket);
ll_apr_warn_status(status);
return false;
}
return true;
}
void disconnect_smtp()
{
if(gMailSocket)
{
apr_status_t status = apr_socket_close(gMailSocket);
ll_apr_warn_status(status);
gMailSocket = NULL;
}
}
// Returns TRUE on success.
// message should NOT be SMTP escaped.
// static
BOOL LLMail::send(
const char* from_name,
const char* from_address,
const char* to_name,
const char* to_address,
const char* subject,
const char* message,
const LLSD& headers)
{
std::string header = buildSMTPTransaction(
from_name,
from_address,
to_name,
to_address,
subject,
headers);
if(header.empty())
{
return FALSE;
}
std::string message_str;
if(message)
{
message_str = message;
}
bool rv = send(header, message_str, to_address, from_address);
if(rv) return TRUE;
return FALSE;
}
// static
void LLMail::init(const std::string& hostname, apr_pool_t* pool)
{
gMailSocket = NULL;
if(hostname.empty() || !pool)
{
gMailPool = NULL;
gSockAddr = NULL;
}
else
{
gMailPool = pool;
// collect all the information into a socaddr sturcture. the
// documentation is a bit unclear, but I either have to
// specify APR_UNSPEC or not specify any flags. I am not sure
// which option is better.
apr_status_t status = apr_sockaddr_info_get(
&gSockAddr,
hostname.c_str(),
APR_UNSPEC,
25,
APR_IPV4_ADDR_OK,
gMailPool);
ll_apr_warn_status(status);
}
}
// static
void LLMail::enable(bool mail_enabled)
{
gMailEnabled = mail_enabled;
}
// Test a subject line for RFC2822 compliance.
static bool valid_subject_chars(const char *subject)
{
for (; *subject != '\0'; subject++)
{
unsigned char c = *subject;
if (c == '\xa' || c == '\xd' || c > '\x7f')
{
return false;
}
}
return true;
}
// static
std::string LLMail::buildSMTPTransaction(
const char* from_name,
const char* from_address,
const char* to_name,
const char* to_address,
const char* subject,
const LLSD& headers)
{
if(!from_address || !to_address)
{
LL_INFOS() << "send_mail build_smtp_transaction reject: missing to and/or"
<< " from address." << LL_ENDL;
return std::string();
}
if(!valid_subject_chars(subject))
{
LL_INFOS() << "send_mail build_smtp_transaction reject: bad subject header: "
<< "to=<" << to_address
<< ">, from=<" << from_address << ">"
<< LL_ENDL;
return std::string();
}
std::ostringstream from_fmt;
if(from_name && from_name[0])
{
// "My Name" <myaddress@example.com>
from_fmt << "\"" << from_name << "\" <" << from_address << ">";
}
else
{
// <myaddress@example.com>
from_fmt << "<" << from_address << ">";
}
std::ostringstream to_fmt;
if(to_name && to_name[0])
{
to_fmt << "\"" << to_name << "\" <" << to_address << ">";
}
else
{
to_fmt << "<" << to_address << ">";
}
std::ostringstream header;
header
<< "HELO lindenlab.com\r\n"
<< "MAIL FROM:<" << from_address << ">\r\n"
<< "RCPT TO:<" << to_address << ">\r\n"
<< "DATA\r\n"
<< "From: " << from_fmt.str() << "\r\n"
<< "To: " << to_fmt.str() << "\r\n"
<< "Subject: " << subject << "\r\n";
if(headers.isMap())
{
LLSD::map_const_iterator iter = headers.beginMap();
LLSD::map_const_iterator end = headers.endMap();
for(; iter != end; ++iter)
{
header << (*iter).first << ": " << ((*iter).second).asString()
<< "\r\n";
}
}
header << "\r\n";
return header.str();
}
// static
bool LLMail::send(
const std::string& header,
const std::string& raw_message,
const char* from_address,
const char* to_address)
{
if(!from_address || !to_address)
{
LL_INFOS() << "send_mail reject: missing to and/or from address."
<< LL_ENDL;
return false;
}
// remove any "." SMTP commands to prevent injection (DEV-35777)
// we don't need to worry about "\r\n.\r\n" because of the
// "\n" --> "\n\n" conversion going into rfc2822_msg below
std::string message = raw_message;
std::string bad_string = "\n.\n";
std::string good_string = "\n..\n";
while (1)
{
int index = message.find(bad_string);
if (index == std::string::npos) break;
message.replace(index, bad_string.size(), good_string);
}
// convert all "\n" into "\r\n"
std::ostringstream rfc2822_msg;
for(U32 i = 0; i < message.size(); ++i)
{
switch(message[i])
{
case '\0':
break;
case '\n':
// *NOTE: this is kinda busted if we're fed \r\n
rfc2822_msg << "\r\n";
break;
default:
rfc2822_msg << message[i];
break;
}
}
if(!gMailEnabled)
{
LL_INFOS() << "send_mail reject: mail system is disabled: to=<"
<< to_address << ">, from=<" << from_address
<< ">" << LL_ENDL;
// Any future interface to SMTP should return this as an
// error. --mark
return true;
}
if(!gSockAddr)
{
LL_WARNS() << "send_mail reject: mail system not initialized: to=<"
<< to_address << ">, from=<" << from_address
<< ">" << LL_ENDL;
return false;
}
if(!connect_smtp())
{
LL_WARNS() << "send_mail reject: SMTP connect failure: to=<"
<< to_address << ">, from=<" << from_address
<< ">" << LL_ENDL;
return false;
}
std::ostringstream smtp_fmt;
smtp_fmt << header << rfc2822_msg.str() << "\r\n" << ".\r\n" << "QUIT\r\n";
std::string smtp_transaction = smtp_fmt.str();
size_t original_size = smtp_transaction.size();
apr_size_t send_size = original_size;
apr_status_t status = apr_socket_send(
gMailSocket,
smtp_transaction.c_str(),
(apr_size_t*)&send_size);
disconnect_smtp();
if(ll_apr_warn_status(status))
{
LL_WARNS() << "send_mail socket failure: unable to write "
<< "to=<" << to_address
<< ">, from=<" << from_address << ">"
<< ", bytes=" << original_size
<< ", sent=" << send_size << LL_ENDL;
return false;
}
if(send_size >= LL_MAX_KNOWN_GOOD_MAIL_SIZE)
{
LL_WARNS() << "send_mail message has been shown to fail in testing "
<< "when sending messages larger than " << LL_MAX_KNOWN_GOOD_MAIL_SIZE
<< " bytes. The next log about success is potentially a lie." << LL_ENDL;
}
LL_DEBUGS() << "send_mail success: "
<< "to=<" << to_address
<< ">, from=<" << from_address << ">"
<< ", bytes=" << original_size
<< ", sent=" << send_size << LL_ENDL;
#if LL_LOG_ENTIRE_MAIL_MESSAGE_ON_SEND
LL_INFOS() << rfc2822_msg.str() << LL_ENDL;
#endif
return true;
}
// static
std::string LLMail::encryptIMEmailAddress(const LLUUID& from_agent_id,
const LLUUID& to_agent_id,
U32 time,
const U8* secret,
size_t secret_size)
{
#if LL_WINDOWS
return "blowfish-not-supported-on-windows";
#else
size_t data_size = 4 + UUID_BYTES + UUID_BYTES;
// Convert input data into a binary blob
std::vector<U8> data;
data.resize(data_size);
// *NOTE: This may suffer from endian issues. Could be htolememcpy.
memcpy(&data[0], &time, 4);
memcpy(&data[4], &from_agent_id.mData[0], UUID_BYTES);
memcpy(&data[4 + UUID_BYTES], &to_agent_id.mData[0], UUID_BYTES);
// Encrypt the blob
LLBlowfishCipher cipher(secret, secret_size);
size_t encrypted_size = cipher.requiredEncryptionSpace(data.size());
U8* encrypted = new U8[encrypted_size];
cipher.encrypt(&data[0], data_size, encrypted, encrypted_size);
std::string address = LLBase32::encode(encrypted, encrypted_size);
// Make it more pretty for humans.
LLStringUtil::toLower(address);
delete [] encrypted;
return address;
#endif
}
/**
* @file llmail.h
* @brief smtp helper functions.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLMAIL_H
#define LL_LLMAIL_H
typedef struct apr_pool_t apr_pool_t;
#include "llsd.h"
class LLMail
{
public:
// if hostname is NULL, then the host is resolved as 'mail'
static void init(const std::string& hostname, apr_pool_t* pool);
// Allow all email transmission to be disabled/enabled.
static void enable(bool mail_enabled);
/**
* @brief send an email
* @param from_name The name of the email sender
* @param from_address The email address for the sender
* @param to_name The name of the email recipient
* @param to_address The email recipient address
* @param subject The subject of the email
* @param headers optional X-Foo headers in an llsd map.
* @return Returns TRUE if the call succeeds, FALSE otherwise.
*
* Results in:
* From: "from_name" <from_address>
* To: "to_name" <to_address>
* Subject: subject
*
* message
*/
static BOOL send(
const char* from_name,
const char* from_address,
const char* to_name,
const char* to_address,
const char* subject,
const char* message,
const LLSD& headers = LLSD());
/**
* @brief build the complete smtp transaction & header for use in an
* mail.
*
* @param from_name The name of the email sender
* @param from_address The email address for the sender
* @param to_name The name of the email recipient
* @param to_address The email recipient address
* @param subject The subject of the email
* @param headers optional X-Foo headers in an llsd map.
* @return Returns the complete SMTP transaction mail header.
*/
static std::string buildSMTPTransaction(
const char* from_name,
const char* from_address,
const char* to_name,
const char* to_address,
const char* subject,
const LLSD& headers = LLSD());
/**
* @brief send an email with header and body.
*
* @param header The email header. Use build_mail_header().
* @param message The unescaped email message.
* @param from_address Used for debugging
* @param to_address Used for debugging
* @return Returns true if the message could be sent.
*/
static bool send(
const std::string& header,
const std::string& message,
const char* from_address,
const char* to_address);
// IM-to-email sessions use a "session id" based on an encrypted
// combination of from agent_id, to agent_id, and timestamp. When
// a user replies to an email we use the from_id to determine the
// sender's name and the to_id to route the message. The address
// is encrypted to prevent users from building addresses to spoof
// IMs from other users. The timestamps allow the "sessions" to
// expire, in case one of the sessions is stolen/hijacked.
//
// indra/tools/mailglue is responsible for parsing the inbound mail.
//
// secret: binary blob passed to blowfish, max length 56 bytes
// secret_size: length of blob, in bytes
//
// Returns: "base64" encoded email local-part, with _ and - as the
// non-alphanumeric characters. This allows better compatibility
// with email systems than the default / and + extra chars. JC
static std::string encryptIMEmailAddress(
const LLUUID& from_agent_id,
const LLUUID& to_agent_id,
U32 time,
const U8* secret,
size_t secret_size);
};
extern const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE;
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment