merge -r 57761:57967 im-email-session-3, removes database load from IM to email session tracking, introduces new format for email return addresses
parent
4feabe4a9c
commit
12ac04231b
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file llbase64.cpp
|
||||
* @brief Wrapper for apr base64 encoding that returns a std::string
|
||||
* @author James Cook
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llbase64.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "apr-1/apr_base64.h"
|
||||
|
||||
|
||||
// static
|
||||
std::string LLBase64::encode(const U8* input, size_t input_size)
|
||||
{
|
||||
std::string output;
|
||||
if (input
|
||||
&& input_size > 0)
|
||||
{
|
||||
// Yes, it returns int.
|
||||
int b64_buffer_length = apr_base64_encode_len(input_size);
|
||||
char* b64_buffer = new char[b64_buffer_length];
|
||||
|
||||
// This is faster than apr_base64_encode() if you know
|
||||
// you're not on an EBCDIC machine. Also, the output is
|
||||
// null terminated, even though the documentation doesn't
|
||||
// specify. See apr_base64.c for details. JC
|
||||
b64_buffer_length = apr_base64_encode_binary(
|
||||
b64_buffer,
|
||||
input,
|
||||
input_size);
|
||||
output.assign(b64_buffer);
|
||||
delete[] b64_buffer;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* @file llbase64.h
|
||||
* @brief Wrapper for apr base64 encoding that returns a std::string
|
||||
* @author James Cook
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#ifndef LLBASE64_H
|
||||
#define LLBASE64_h
|
||||
|
||||
class LLBase64
|
||||
{
|
||||
public:
|
||||
static std::string encode(const U8* input, size_t input_size);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -171,6 +171,7 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
|
|||
else
|
||||
{
|
||||
// *FIX: memory inefficient.
|
||||
// *TODO: convert to use LLBase64
|
||||
ostr << pre << "<binary encoding=\"base64\">";
|
||||
int b64_buffer_length = apr_base64_encode_len(buffer.size());
|
||||
char* b64_buffer = new char[b64_buffer_length];
|
||||
|
|
|
|||
|
|
@ -904,7 +904,7 @@ void LLStringBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T r
|
|||
|
||||
//static
|
||||
template<class T>
|
||||
void LLStringBase<T>::replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab )
|
||||
void LLStringBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab )
|
||||
{
|
||||
llassert( spaces_per_tab >= 0 );
|
||||
|
||||
|
|
@ -913,19 +913,19 @@ void LLStringBase<T>::replaceTabsWithSpaces( std::basic_string<T>& string, size_
|
|||
|
||||
LLStringBase<T> out_str;
|
||||
// Replace tabs with spaces
|
||||
for (size_type i = 0; i < string.length(); i++)
|
||||
for (size_type i = 0; i < str.length(); i++)
|
||||
{
|
||||
if (string[i] == TAB)
|
||||
if (str[i] == TAB)
|
||||
{
|
||||
for (size_type j = 0; j < spaces_per_tab; j++)
|
||||
out_str += SPACE;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_str += string[i];
|
||||
out_str += str[i];
|
||||
}
|
||||
}
|
||||
string = out_str;
|
||||
str = out_str;
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include "llinventory.h"
|
||||
|
||||
#include "lldbstrings.h"
|
||||
#include "llcrypto.h"
|
||||
#include "llxorcipher.h"
|
||||
#include "llsd.h"
|
||||
#include "message.h"
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
* @file llblowcipher.cpp
|
||||
* @brief Wrapper around OpenSSL Blowfish encryption algorithm.
|
||||
*
|
||||
* We do not have OpenSSL headers or libraries on Windows, so this
|
||||
* class only works on Linux.
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llblowfishcipher.h"
|
||||
|
||||
|
||||
LLBlowfishCipher::LLBlowfishCipher(const U8* secret, size_t secret_size)
|
||||
: LLCipher()
|
||||
{
|
||||
llassert(secret);
|
||||
|
||||
mSecretSize = secret_size;
|
||||
mSecret = new U8[mSecretSize];
|
||||
memcpy(mSecret, secret, mSecretSize);
|
||||
}
|
||||
|
||||
LLBlowfishCipher::~LLBlowfishCipher()
|
||||
{
|
||||
delete [] mSecret;
|
||||
mSecret = NULL;
|
||||
}
|
||||
|
||||
|
||||
#if LL_LINUX
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
// virtual
|
||||
U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
{
|
||||
if (!src || !src_len || !dst || !dst_len) return 0;
|
||||
if (src_len > dst_len) return 0;
|
||||
|
||||
// OpenSSL uses "cipher contexts" to hold encryption parameters.
|
||||
EVP_CIPHER_CTX context;
|
||||
EVP_CIPHER_CTX_init(&context);
|
||||
|
||||
// We want a blowfish cyclic block chain cipher, but need to set
|
||||
// the key length before we pass in a key, so call EncryptInit
|
||||
// first with NULLs.
|
||||
EVP_EncryptInit_ex(&context, EVP_bf_cbc(), NULL, NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length(&context, (int)mSecretSize);
|
||||
|
||||
// Complete initialization. Per EVP_EncryptInit man page, the
|
||||
// cipher pointer must be NULL. Apparently initial_vector must
|
||||
// be 8 bytes for blowfish, as this is the block size.
|
||||
unsigned char initial_vector[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
EVP_EncryptInit_ex(&context, NULL, NULL, mSecret, initial_vector);
|
||||
|
||||
int blocksize = EVP_CIPHER_CTX_block_size(&context);
|
||||
int keylen = EVP_CIPHER_CTX_key_length(&context);
|
||||
int iv_length = EVP_CIPHER_CTX_iv_length(&context);
|
||||
lldebugs << "LLBlowfishCipher blocksize " << blocksize
|
||||
<< " keylen " << keylen
|
||||
<< " iv_len " << iv_length
|
||||
<< llendl;
|
||||
|
||||
int output_len = 0;
|
||||
if (!EVP_EncryptUpdate(&context,
|
||||
dst,
|
||||
&output_len,
|
||||
src,
|
||||
src_len))
|
||||
{
|
||||
llwarns << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << llendl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// There may be some final data left to encrypt if the input is
|
||||
// not an exact multiple of the block size.
|
||||
int temp_len = 0;
|
||||
if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
|
||||
{
|
||||
llwarns << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << llendl;
|
||||
return 0;
|
||||
}
|
||||
output_len += temp_len;
|
||||
return output_len;
|
||||
}
|
||||
|
||||
// virtual
|
||||
U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
{
|
||||
llerrs << "LLBlowfishCipher decrypt unsupported" << llendl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual
|
||||
U32 LLBlowfishCipher::requiredEncryptionSpace(U32 len) const
|
||||
{
|
||||
// *HACK: We know blowfish uses an 8 byte block size.
|
||||
// Oddly, sometimes EVP_Encrypt produces an extra block
|
||||
// if the input is an exact multiple of the block size.
|
||||
// So round up.
|
||||
const U32 BLOCK_SIZE = 8;
|
||||
len += BLOCK_SIZE;
|
||||
len -= (len % BLOCK_SIZE);
|
||||
return len;
|
||||
}
|
||||
|
||||
#else // !LL_LINUX
|
||||
|
||||
// virtual
|
||||
U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
{
|
||||
llerrs << "LLBlowfishCipher only supported on Linux" << llendl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual
|
||||
U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
{
|
||||
llerrs << "LLBlowfishCipher only supported on Linux" << llendl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual
|
||||
U32 LLBlowfishCipher::requiredEncryptionSpace(U32 len) const
|
||||
{
|
||||
llerrs << "LLBlowfishCipher only supported on Linux" << llendl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* @file llblowfishcipher.h
|
||||
* @brief A symmetric block cipher, designed in 1993 by Bruce Schneier.
|
||||
* We use it because it has an 8 byte block size, allowing encryption of
|
||||
* two UUIDs and a timestamp (16x2 + 4 = 36 bytes) with only 40 bytes of
|
||||
* output. AES has a block size of 32 bytes, so this would require 64 bytes.
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#ifndef LLBLOWFISHCIPHER_H
|
||||
#define LLBLOWFISHCIPHER_H
|
||||
|
||||
#include "llcipher.h"
|
||||
|
||||
|
||||
class LLBlowfishCipher : public LLCipher
|
||||
{
|
||||
public:
|
||||
// Secret may be up to 56 bytes in length per Blowfish spec.
|
||||
LLBlowfishCipher(const U8* secret, size_t secret_size);
|
||||
virtual ~LLBlowfishCipher();
|
||||
|
||||
// See llcipher.h for documentation.
|
||||
/*virtual*/ U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
|
||||
/*virtual*/ U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
|
||||
/*virtual*/ U32 requiredEncryptionSpace(U32 src_len) const;
|
||||
|
||||
#ifdef _DEBUG
|
||||
static BOOL testHarness();
|
||||
#endif
|
||||
|
||||
private:
|
||||
U8* mSecret;
|
||||
size_t mSecretSize;
|
||||
};
|
||||
|
||||
#endif // LL_LLCRYPTO_H
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* @file llcipher.h
|
||||
* @brief Abstract base class for encryption ciphers.
|
||||
*
|
||||
* Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#ifndef LLCIPHER_H
|
||||
#define LLCIPHER_H
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLCipher
|
||||
//
|
||||
// Abstract base class for a cipher object.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLCipher
|
||||
{
|
||||
public:
|
||||
virtual ~LLCipher() {}
|
||||
|
||||
// encrypt src and place result into dst. returns TRUE if
|
||||
// Returns number of bytes written into dst, or 0 on error.
|
||||
virtual U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) = 0;
|
||||
|
||||
// decrypt src and place result into dst.
|
||||
// Returns number of bytes written into dst, or 0 on error.
|
||||
virtual U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) = 0;
|
||||
|
||||
// returns the minimum amount of space required to encrypt for a
|
||||
// unencrypted source buffer of length len.
|
||||
// *NOTE: This is estimated space and you should check the return value
|
||||
// of the encrypt function.
|
||||
virtual U32 requiredEncryptionSpace(U32 src_len) const = 0 ;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -248,6 +248,7 @@ void LLFilterSD2XMLRPC::streamOut(std::ostream& ostr, const LLSD& sd)
|
|||
LLSD::Binary buffer = sd.asBinary();
|
||||
if(!buffer.empty())
|
||||
{
|
||||
// *TODO: convert to LLBase64
|
||||
int b64_buffer_length = apr_base64_encode_len(buffer.size());
|
||||
char* b64_buffer = new char[b64_buffer_length];
|
||||
b64_buffer_length = apr_base64_encode_binary(
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmail.h"
|
||||
|
||||
// APR on Windows needs full windows headers
|
||||
#ifdef LL_WINDOWS
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
|
|
@ -19,14 +21,16 @@
|
|||
#include <sstream>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include "llmail.h"
|
||||
|
||||
#include "apr-1/apr_pools.h"
|
||||
#include "apr-1/apr_network_io.h"
|
||||
|
||||
#include "llapr.h"
|
||||
#include "llbase64.h" // IM-to-email address
|
||||
#include "llblowfishcipher.h"
|
||||
#include "llerror.h"
|
||||
#include "llhost.h"
|
||||
#include "llstring.h"
|
||||
#include "lluuid.h"
|
||||
#include "net.h"
|
||||
|
||||
//
|
||||
|
|
@ -86,11 +90,12 @@ void disconnect_smtp()
|
|||
|
||||
// Returns TRUE on success.
|
||||
// message should NOT be SMTP escaped.
|
||||
BOOL send_mail(const char* from_name, const char* from_address,
|
||||
// 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)
|
||||
{
|
||||
std::string header = build_smtp_transaction(
|
||||
std::string header = buildSMTPTransaction(
|
||||
from_name,
|
||||
from_address,
|
||||
to_name,
|
||||
|
|
@ -106,12 +111,13 @@ BOOL send_mail(const char* from_name, const char* from_address,
|
|||
{
|
||||
message_str = message;
|
||||
}
|
||||
bool rv = send_mail(header, message_str, to_address, from_address);
|
||||
bool rv = send(header, message_str, to_address, from_address);
|
||||
if(rv) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void init_mail(const std::string& hostname, apr_pool_t* pool)
|
||||
// static
|
||||
void LLMail::init(const std::string& hostname, apr_pool_t* pool)
|
||||
{
|
||||
gMailSocket = NULL;
|
||||
if(hostname.empty() || !pool)
|
||||
|
|
@ -138,12 +144,14 @@ void init_mail(const std::string& hostname, apr_pool_t* pool)
|
|||
}
|
||||
}
|
||||
|
||||
void enable_mail(bool mail_enabled)
|
||||
// static
|
||||
void LLMail::enable(bool mail_enabled)
|
||||
{
|
||||
gMailEnabled = mail_enabled;
|
||||
}
|
||||
|
||||
std::string build_smtp_transaction(
|
||||
// static
|
||||
std::string LLMail::buildSMTPTransaction(
|
||||
const char* from_name,
|
||||
const char* from_address,
|
||||
const char* to_name,
|
||||
|
|
@ -197,7 +205,8 @@ std::string build_smtp_transaction(
|
|||
return header.str();
|
||||
}
|
||||
|
||||
bool send_mail(
|
||||
// static
|
||||
bool LLMail::send(
|
||||
const std::string& header,
|
||||
const std::string& message,
|
||||
const char* from_address,
|
||||
|
|
@ -290,3 +299,56 @@ bool send_mail(
|
|||
#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)
|
||||
{
|
||||
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 htonmemcpy.
|
||||
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);
|
||||
|
||||
// Base64 encoded and replace the pieces of base64 that are less compatible
|
||||
// with e-mail local-parts.
|
||||
// See RFC-4648 "Base 64 Encoding with URL and Filename Safe Alphabet"
|
||||
std::string address = LLBase64::encode(encrypted, encrypted_size);
|
||||
LLString::replaceChar(address, '+', '-');
|
||||
LLString::replaceChar(address, '/', '_');
|
||||
|
||||
// Strip padding = signs, see RFC
|
||||
size_t extra_bytes = encrypted_size % 3;
|
||||
size_t padding_size = 0;
|
||||
if (extra_bytes == 0)
|
||||
{
|
||||
padding_size = 0;
|
||||
}
|
||||
else if (extra_bytes == 1)
|
||||
{
|
||||
padding_size = 2;
|
||||
}
|
||||
else if (extra_bytes == 2)
|
||||
{
|
||||
padding_size = 1;
|
||||
}
|
||||
|
||||
address.resize(address.size() - padding_size);
|
||||
|
||||
delete [] encrypted;
|
||||
|
||||
return address;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,55 +11,84 @@
|
|||
|
||||
typedef struct apr_pool_t apr_pool_t;
|
||||
|
||||
// if hostname is NULL, then the host is resolved as 'mail'
|
||||
void init_mail(const std::string& hostname, apr_pool_t* pool);
|
||||
class LLUUID;
|
||||
|
||||
// Allow all email transmission to be disabled/enabled.
|
||||
void enable_mail(bool mail_enabled);
|
||||
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);
|
||||
|
||||
// returns TRUE if the call succeeds, FALSE otherwise.
|
||||
//
|
||||
// Results in:
|
||||
// From: "from_name" <from_address>
|
||||
// To: "to_name" <to_address>
|
||||
// Subject: subject
|
||||
// message
|
||||
BOOL send_mail(const char* from_name, const char* from_address,
|
||||
const char* to_name, const char* to_address,
|
||||
const char* subject, const char* message);
|
||||
// Allow all email transmission to be disabled/enabled.
|
||||
static void enable(bool mail_enabled);
|
||||
|
||||
/**
|
||||
* @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_name The email recipient address
|
||||
* @param subject The subject of the email
|
||||
* @return Returns the complete SMTP transaction mail header.
|
||||
*/
|
||||
std::string build_smtp_transaction(
|
||||
const char* from_name,
|
||||
const char* from_address,
|
||||
const char* to_name,
|
||||
const char* to_address,
|
||||
const char* subject);
|
||||
// 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);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
bool send_mail(
|
||||
const std::string& header,
|
||||
const std::string& message,
|
||||
const char* from_address,
|
||||
const char* to_address);
|
||||
/**
|
||||
* @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_name The email recipient address
|
||||
* @param subject The subject of the email
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,33 +8,33 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llcrypto.h"
|
||||
#include "llnullcipher.h"
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class LLNullCipher
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
BOOL LLNullCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
U32 LLNullCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
{
|
||||
if((src_len == dst_len) && src && dst)
|
||||
{
|
||||
memmove(dst, src, src_len);
|
||||
return TRUE;
|
||||
return src_len;
|
||||
}
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL LLNullCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
U32 LLNullCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
{
|
||||
if((src_len == dst_len) && src && dst)
|
||||
{
|
||||
memmove(dst, src, src_len);
|
||||
return TRUE;
|
||||
return src_len;
|
||||
}
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
U32 LLNullCipher::requiredEncryptionSpace(U32 len)
|
||||
U32 LLNullCipher::requiredEncryptionSpace(U32 len) const
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @file llnullcipher.h
|
||||
*
|
||||
* Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#ifndef LLNULLCIPHER_H
|
||||
#define LLNULLCIPHER_H
|
||||
|
||||
#include "llcipher.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLNullCipher
|
||||
//
|
||||
// A class which implements LLCipher, but does not transform src
|
||||
// during encryption.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLNullCipher : public LLCipher
|
||||
{
|
||||
public:
|
||||
LLNullCipher() {}
|
||||
virtual ~LLNullCipher() {}
|
||||
virtual U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
|
||||
virtual U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
|
||||
virtual U32 requiredEncryptionSpace(U32 src_len) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llcrypto.h"
|
||||
#include "llxorcipher.h"
|
||||
|
||||
#include "llerror.h"
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
|
|
@ -44,25 +45,26 @@ LLXORCipher& LLXORCipher::operator=(const LLXORCipher& cipher)
|
|||
return *this;
|
||||
}
|
||||
|
||||
BOOL LLXORCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
U32 LLXORCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
{
|
||||
if(!src || !src_len || !dst || !dst_len || !mPad) return FALSE;
|
||||
if(!src || !src_len || !dst || !dst_len || !mPad) return 0;
|
||||
U8* pad_end = mPad + mPadLen;
|
||||
while(src_len--)
|
||||
U32 count = src_len;
|
||||
while(count--)
|
||||
{
|
||||
*dst++ = *src++ ^ *mHead++;
|
||||
if(mHead >= pad_end) mHead = mPad;
|
||||
}
|
||||
return TRUE;
|
||||
return src_len;
|
||||
}
|
||||
|
||||
BOOL LLXORCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
U32 LLXORCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
||||
{
|
||||
// xor is a symetric cipher, thus, just call the other function.
|
||||
return encrypt(src, src_len, dst, dst_len);
|
||||
}
|
||||
|
||||
U32 LLXORCipher::requiredEncryptionSpace(U32 len)
|
||||
U32 LLXORCipher::requiredEncryptionSpace(U32 len) const
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @file llxorcipher.h
|
||||
*
|
||||
* Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#ifndef LLXORCIPHER_H
|
||||
#define LLXORCIPHER_H
|
||||
|
||||
#include "llcipher.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLXORCipher
|
||||
//
|
||||
// Implementation of LLCipher which encrypts using a XOR pad.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLXORCipher : public LLCipher
|
||||
{
|
||||
public:
|
||||
LLXORCipher(const U8* pad, U32 pad_len);
|
||||
LLXORCipher(const LLXORCipher& cipher);
|
||||
virtual ~LLXORCipher();
|
||||
LLXORCipher& operator=(const LLXORCipher& cipher);
|
||||
|
||||
// Cipher functions
|
||||
/*virtual*/ U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
|
||||
/*virtual*/ U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
|
||||
/*virtual*/ U32 requiredEncryptionSpace(U32 src_len) const;
|
||||
|
||||
// special syntactic-sugar since xor can be performed in place.
|
||||
BOOL encrypt(U8* buf, U32 len) { return encrypt((const U8*)buf, len, buf, len); }
|
||||
BOOL decrypt(U8* buf, U32 len) { return decrypt((const U8*)buf, len, buf, len); }
|
||||
|
||||
#ifdef _DEBUG
|
||||
// This function runs tests to make sure the crc is
|
||||
// working. Returns TRUE if it is.
|
||||
static BOOL testHarness();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void init(const U8* pad, U32 pad_len);
|
||||
U8* mPad;
|
||||
U8* mHead;
|
||||
U32 mPadLen;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -25,7 +25,6 @@
|
|||
#include "audiosettings.h"
|
||||
#include "llcachename.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llcrypto.h"
|
||||
#include "lldir.h"
|
||||
#include "lleconomy.h"
|
||||
#include "llerrorcontrol.h"
|
||||
|
|
@ -46,6 +45,7 @@
|
|||
#include "llversion.h"
|
||||
#include "llvfs.h"
|
||||
#include "llwindow.h" // for shell_open
|
||||
#include "llxorcipher.h" // saved password, MAC address
|
||||
#include "message.h"
|
||||
#include "v3math.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -151,7 +151,6 @@
|
|||
#include "llcachename.h"
|
||||
#include "llcallbacklisth.h"
|
||||
#include "llcircuit.h"
|
||||
#include "llcrypto.h"
|
||||
#include "lldatapacker.h"
|
||||
#include "lldbstrings.h"
|
||||
#include "lldispatcher.h"
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
.A„Ä3ŒLÜE ``òøÝKÛ@¼ûÇ;M[ÚBë·ø„>ËÊC—'
|
||||
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
01234567890123456789012345678901234
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# *TODO: specify test count here
|
||||
use Test::More qw(no_plan);
|
||||
|
||||
use Crypt::CBC;
|
||||
use MIME::Base64;
|
||||
|
||||
my $init_vector = "\x00" x 8;
|
||||
# my $key = pack("H*", "ef5a8376eb0c99fe0dafa487d15bec19cae63d1e25fe31d8d92f7ab0398246d70ee733108e47360e16359654571cf5bab6c3375b42cee4fa");
|
||||
# my $key = "d263eb8a78034e40";
|
||||
#"8d082918aa369174";
|
||||
my $key = "\x00" x 16;
|
||||
|
||||
my $cipher = Crypt::CBC->new( { cipher => 'Blowfish',
|
||||
regenerate_key => 0,
|
||||
key => $key,
|
||||
iv => $init_vector,
|
||||
header => 'none',
|
||||
prepend_iv => 0,
|
||||
keysize => 16 } );
|
||||
|
||||
#my $blocks = $cipher->blocksize();
|
||||
#print "blocksize $blocks\n";
|
||||
|
||||
my $len;
|
||||
my $input = "01234567890123456789012345678901234\n";
|
||||
#my $input = "a whale of a tale I tell you lad, a whale of a tale for me, a whale of a tale and the fiddlers three";
|
||||
$len = length($input);
|
||||
is ($len, 36, "input length");
|
||||
|
||||
$len = length($key);
|
||||
is ($len, 16, "key length");
|
||||
|
||||
|
||||
my $encrypted = $cipher->encrypt($input);
|
||||
is (length($encrypted), 40, "encrypted length");
|
||||
|
||||
open(FH, "blowfish.1.bin");
|
||||
my $bin = scalar <FH>;
|
||||
is ($encrypted, $bin, "matches openssl");
|
||||
close(FH);
|
||||
|
||||
my $base64 = encode_base64($encrypted);
|
||||
is ($base64, "LkGExDOMTNxFIGBg8gP43UvbQLz7xztNWwYF2kLrtwT4hD7LykOXJw==\n",
|
||||
"base64 output");
|
||||
|
||||
my $unbase64 = decode_base64($base64);
|
||||
is( $encrypted, $unbase64, "reverse base64" );
|
||||
|
||||
my $output = $cipher->decrypt($unbase64);
|
||||
is ($input, $output, "reverse encrypt");
|
||||
|
||||
$key = pack("H[32]", "526a1e07a19dbaed84c4ff08a488d15e");
|
||||
$cipher = Crypt::CBC->new( { cipher => 'Blowfish',
|
||||
regenerate_key => 0,
|
||||
key => $key,
|
||||
iv => $init_vector,
|
||||
header => 'none',
|
||||
prepend_iv => 0,
|
||||
keysize => 16 } );
|
||||
$encrypted = $cipher->encrypt($input);
|
||||
is (length($encrypted), 40, "uuid encrypted length");
|
||||
$output = $cipher->decrypt($encrypted);
|
||||
is ($input, $output, "uuid reverse encrypt");
|
||||
|
||||
open(FH, "blowfish.2.bin");
|
||||
$bin = scalar <FH>;
|
||||
close(FH);
|
||||
is( $encrypted, $bin, "uuid matches openssl" );
|
||||
|
||||
print encode_base64($encrypted);
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* @file llblowfish_tut.cpp
|
||||
* @author James Cook, james@lindenlab.com
|
||||
* @date 2007-02-04
|
||||
*
|
||||
* Data files generated with:
|
||||
* openssl enc -bf-cbc -in blowfish.digits.txt -out blowfish.1.bin -K 00000000000000000000000000000000 -iv 0000000000000000 -p
|
||||
* openssl enc -bf-cbc -in blowfish.digits.txt -out blowfish.2.bin -K 526a1e07a19dbaed84c4ff08a488d15e -iv 0000000000000000 -p
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "lltut.h"
|
||||
|
||||
#include "llblowfishcipher.h"
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include "lluuid.h"
|
||||
|
||||
namespace tut
|
||||
{
|
||||
class LLData
|
||||
{
|
||||
public:
|
||||
unsigned char* mInput;
|
||||
int mInputSize;
|
||||
|
||||
LLData()
|
||||
{
|
||||
// \n to make it easier to create text files
|
||||
// for testing with command line openssl
|
||||
mInput = (unsigned char*)"01234567890123456789012345678901234\n";
|
||||
mInputSize = 36;
|
||||
}
|
||||
|
||||
bool matchFile(const char* filename,
|
||||
const std::string& data)
|
||||
{
|
||||
FILE* fp = fopen(filename, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
// sometimes test is run inside the indra directory
|
||||
std::string path = "test/";
|
||||
path += filename;
|
||||
fp = fopen(path.c_str(), "rb");
|
||||
}
|
||||
if (!fp)
|
||||
{
|
||||
llwarns << "unabled to open " << filename << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string good;
|
||||
good.resize(256);
|
||||
size_t got = fread(&good[0], 1, 256, fp);
|
||||
lldebugs << "matchFile read " << got << llendl;
|
||||
fclose(fp);
|
||||
good.resize(got);
|
||||
|
||||
return (good == data);
|
||||
}
|
||||
};
|
||||
typedef test_group<LLData> blowfish_test;
|
||||
typedef blowfish_test::object blowfish_object;
|
||||
// Create test with name that can be selected on
|
||||
// command line of test app.
|
||||
tut::blowfish_test blowfish("blowfish");
|
||||
|
||||
template<> template<>
|
||||
void blowfish_object::test<1>()
|
||||
{
|
||||
LLUUID blank;
|
||||
LLBlowfishCipher cipher(&blank.mData[0], UUID_BYTES);
|
||||
|
||||
U32 dst_len = cipher.requiredEncryptionSpace(36);
|
||||
ensure("encryption space 36",
|
||||
(dst_len == 40) );
|
||||
|
||||
// Blowfish adds an additional 8-byte block if your
|
||||
// input is an exact multiple of 8
|
||||
dst_len = cipher.requiredEncryptionSpace(8);
|
||||
ensure("encryption space 8",
|
||||
(dst_len == 16) );
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void blowfish_object::test<2>()
|
||||
{
|
||||
LLUUID blank;
|
||||
LLBlowfishCipher cipher(&blank.mData[0], UUID_BYTES);
|
||||
|
||||
std::string result;
|
||||
result.resize(256);
|
||||
U32 count = cipher.encrypt(mInput, mInputSize,
|
||||
(U8*) &result[0], 256);
|
||||
|
||||
ensure("encrypt output count",
|
||||
(count == 40) );
|
||||
result.resize(count);
|
||||
|
||||
ensure("encrypt null key", matchFile("blowfish.1.bin", result));
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void blowfish_object::test<3>()
|
||||
{
|
||||
// same as base64 test id
|
||||
LLUUID id("526a1e07-a19d-baed-84c4-ff08a488d15e");
|
||||
LLBlowfishCipher cipher(&id.mData[0], UUID_BYTES);
|
||||
|
||||
std::string result;
|
||||
result.resize(256);
|
||||
U32 count = cipher.encrypt(mInput, mInputSize,
|
||||
(U8*) &result[0], 256);
|
||||
|
||||
ensure("encrypt output count",
|
||||
(count == 40) );
|
||||
result.resize(count);
|
||||
|
||||
ensure("encrypt real key", matchFile("blowfish.2.bin", result));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue