/*
 * Generate a new session ID.
 *
 * Note that apr_generate_random_bytes() blocks on Linux due to reading from
 * /dev/random.  FreeBSD /dev/random never blocks.  Solaris /dev/random does
 * not seem to block either.  To keep mod_but usable on Linux, we try to not
 * waste any randomness: only read as much as needed and use all bits.
 * On Linux, APR should be compiled to read from /dev/urandom by default.
 */
char *
generate_session_id(request_rec *r)
{
	apr_status_t rc;
	unsigned char rnd[MOD_BUT_SIDBYTES];
	char *sid = apr_pcalloc(r->pool, apr_base64_encode_len(MOD_BUT_SIDBYTES) + 1);

	if (!sid) {
		ERRLOG_CRIT("FATAL: Out of memory");
		return NULL;
	}

	if (APR_SUCCESS != (rc = apr_generate_random_bytes(rnd, MOD_BUT_SIDBYTES))) {
		ERRLOG_CRIT("FATAL: apr_generate_random_bytes returned %d", rc);
		return NULL;
	}

	if (0 >= apr_base64_encode_binary(sid, rnd, MOD_BUT_SIDBYTES)) {
		ERRLOG_CRIT("FATAL: apr_base64_encode failed");
		return NULL;
	}

	ERRLOG_INFO("Session ID generated [%s]", sid);
	return sid;
}
static char * hash_cookie(apr_pool_t *p, uint8_t *secret,int secretLen,unsigned long expires) {
		unsigned char hash[SHA1_DIGEST_LENGTH];
		hmac_sha1(secret, secretLen, (uint8_t *) &expires, sizeof(unsigned int), hash, SHA1_DIGEST_LENGTH);
		int len;
		char *encoded = apr_palloc(p,(SHA1_DIGEST_LENGTH*2)+3);
		len = apr_base64_encode_binary(encoded,hash,SHA1_DIGEST_LENGTH);
		return encoded;
}
static char *hmac_sha1(apr_pool_t *p, char *data, char *key)
{
    apr_sha1_ctx_t context;
    unsigned char digest[APR_SHA1_DIGESTSIZE];
    unsigned char k_ipad[65], k_opad[65];
    unsigned char kt[APR_SHA1_DIGESTSIZE];
    unsigned char *k = (unsigned char *)key;
    int key_len, i;
    char *out;
    int l, outlen;

    key_len = strlen(key);

    if(key_len > BLOCK_SIZE) {
        k = kt;
        key_len = APR_SHA1_DIGESTSIZE;
    }

    memset((void *)k_ipad, 0, sizeof(k_ipad));
    memset((void *)k_opad, 0, sizeof(k_opad));
    memmove(k_ipad, k, key_len);
    memmove(k_opad, k, key_len);

    for (i = 0; i < BLOCK_SIZE; i++) {
        k_ipad[i] ^= 0x36;
        k_opad[i] ^= 0x5c;
    }

    apr_sha1_init(&context);
    apr_sha1_update_binary(&context, k_ipad, 64);
    apr_sha1_update_binary(&context, (const unsigned char *)data, strlen(data));
    apr_sha1_final(digest, &context);

    apr_sha1_init(&context);
    apr_sha1_update_binary(&context, k_opad, 64);
    apr_sha1_update_binary(&context, digest, sizeof(digest));
    apr_sha1_final(digest, &context);

    outlen = apr_base64_encode_len(sizeof(digest));
    out = apr_palloc(p, outlen);
    l = apr_base64_encode_binary(out, digest, sizeof(digest));
    out[l - 2] = '\0';

    return out; 
}
Beispiel #4
0
// 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;
}
void LLFilterSD2XMLRPC::streamOut(std::ostream& ostr, const LLSD& sd)
{
	ostr << "<value>";
	switch(sd.type())
	{
	case LLSD::TypeMap:
	{
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(map) BEGIN" << llendl;
#endif
		ostr << "<struct>";
		if(ostr.fail())
		{
			llinfos << "STREAM FAILURE writing struct" << llendl;
		}
		LLSD::map_const_iterator it = sd.beginMap();
		LLSD::map_const_iterator end = sd.endMap();
		for(; it != end; ++it)
		{
			ostr << "<member><name>" << xml_escape_string((*it).first)
				<< "</name>";
			streamOut(ostr, (*it).second);
			if(ostr.fail())
			{
				llinfos << "STREAM FAILURE writing '" << (*it).first
						<< "' with sd type " << (*it).second.type() << llendl;
			}
			ostr << "</member>";
		}
		ostr << "</struct>";
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(map) END" << llendl;
#endif
		break;
	}
	case LLSD::TypeArray:
	{
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(array) BEGIN" << llendl;
#endif
		ostr << "<array><data>";
		LLSD::array_const_iterator it = sd.beginArray();
		LLSD::array_const_iterator end = sd.endArray();
		for(; it != end; ++it)
		{
			streamOut(ostr, *it);
			if(ostr.fail())
			{
				llinfos << "STREAM FAILURE writing array element sd type "
						<< (*it).type() << llendl;
			}
		}
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(array) END" << llendl;
#endif
		ostr << "</data></array>";
		break;
	}
	case LLSD::TypeUndefined:
		// treat undefined as a bool with a false value.
	case LLSD::TypeBoolean:
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(bool)" << llendl;
#endif
		ostr << "<boolean>" << (sd.asBoolean() ? "1" : "0") << "</boolean>";
		break;
	case LLSD::TypeInteger:
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(int)" << llendl;
#endif
		ostr << "<i4>" << sd.asInteger() << "</i4>";
		break;
	case LLSD::TypeReal:
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(real)" << llendl;
#endif
		ostr << "<double>" << sd.asReal() << "</double>";
		break;
	case LLSD::TypeString:
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(string)" << llendl;
#endif
		ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
		break;
	case LLSD::TypeUUID:
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(uuid)" << llendl;
#endif
		// serialize it as a string
		ostr << "<string>" << sd.asString() << "</string>";
		break;
	case LLSD::TypeURI:
	{
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(uri)" << llendl;
#endif
		// serialize it as a string
		ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
		break;
	}
	case LLSD::TypeBinary:
	{
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(binary)" << llendl;
#endif
		// this is pretty inefficient, but we'll deal with that
		// problem when it becomes one.
		ostr << "<base64>";
		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(
				b64_buffer,
				&buffer[0],
				buffer.size());
			ostr.write(b64_buffer, b64_buffer_length - 1);
			delete[] b64_buffer;
		}
		ostr << "</base64>";
		break;
	}
	case LLSD::TypeDate:
#if LL_SPEW_STREAM_OUT_DEBUGGING
		llinfos << "streamOut(date)" << llendl;
#endif
		// no need to escape this since it will be alpha-numeric.
		ostr << "<dateTime.iso8601>" << sd.asString() << "</dateTime.iso8601>";
		break;
	default:
		// unhandled type
		llwarns << "Unhandled structured data type: " << sd.type()
			<< llendl;
		break;
	}
	ostr << "</value>";
}
S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const
{
	S32 format_count = 1;
	std::string pre;
	std::string post;

	if (options & LLSDFormatter::OPTIONS_PRETTY)
	{
		for (U32 i = 0; i < level; i++)
		{
			pre += "    ";
		}
		post = "\n";
	}

	switch(data.type())
	{
	case LLSD::TypeMap:
		if (0 == data.size())
		{
			ostr << pre << "<map />" << post;
		}
		else
		{
			ostr << pre << "<map>" << post;
			LLSD::map_const_iterator iter = data.beginMap();
			LLSD::map_const_iterator end = data.endMap();
			for (; iter != end; ++iter)
			{
				ostr << pre << "<key>" << escapeString((*iter).first) << "</key>" << post;
				format_count += format_impl((*iter).second, ostr, options, level + 1);
			}
			ostr << pre <<  "</map>" << post;
		}
		break;

	case LLSD::TypeArray:
		if (0 == data.size())
		{
			ostr << pre << "<array />" << post;
		}
		else
		{
			ostr << pre << "<array>" << post;
			LLSD::array_const_iterator iter = data.beginArray();
			LLSD::array_const_iterator end = data.endArray();
			for(; iter != end; ++iter)
			{
				format_count += format_impl(*iter, ostr, options, level + 1);
			}
			ostr << pre << "</array>" << post;
		}
		break;

	case LLSD::TypeUndefined:
		ostr << pre << "<undef />" << post;
		break;

	case LLSD::TypeBoolean:
		ostr << pre << "<boolean>";
		if (mBoolAlpha || (ostr.flags() & std::ios::boolalpha))
		{
			ostr << (data.asBoolean() ? "true" : "false");
		}
		else
		{
			ostr << (data.asBoolean() ? 1 : 0);
		}
		ostr << "</boolean>" << post;
		break;

	case LLSD::TypeInteger:
		ostr << pre << "<integer>" << data.asInteger() << "</integer>" << post;
		break;

	case LLSD::TypeReal:
		ostr << pre << "<real>";
		if (mRealFormat.empty())
		{
			ostr << data.asReal();
		}
		else
		{
			formatReal(data.asReal(), ostr);
		}
		ostr << "</real>" << post;
		break;

	case LLSD::TypeUUID:
		if (data.asUUID().isNull())
		{
			ostr << pre << "<uuid />" << post;
		}
		else
		{
			ostr << pre << "<uuid>" << data.asUUID() << "</uuid>" << post;
		}
		break;

	case LLSD::TypeString:
		if (data.asString().empty()) ostr << pre << "<string />" << post;
		else ostr << pre << "<string>" << escapeString(data.asString()) <<"</string>" << post;
		break;

	case LLSD::TypeDate:
		ostr << pre << "<date>" << data.asDate() << "</date>" << post;
		break;

	case LLSD::TypeURI:
		ostr << pre << "<uri>" << escapeString(data.asString()) << "</uri>" << post;
		break;

	case LLSD::TypeBinary:
	{
		LLSD::Binary buffer = data.asBinary();
		if (buffer.empty())
		{
			ostr << pre << "<binary />" << post;
		}
		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];
			b64_buffer_length = apr_base64_encode_binary(b64_buffer,
														 &buffer[0],
														 buffer.size());
			ostr.write(b64_buffer, b64_buffer_length - 1);
			delete[] b64_buffer;
			ostr << "</binary>" << post;
		}
		break;
	}

	default:
		// *NOTE: This should never happen.
		ostr << pre << "<undef />" << post;
		break;
	}
	return format_count;
}