blob: 6c2220474fe69c308b0be01a81bbc65200bb956e [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ajp_logon.h"
#include "ajp.h"
/**
* Binary to hex C String (null terminated)
*
* @param org byte array to transform
* @param dst string result
* @param n len of byte array
* @return APR_SUCCESS or error
*/
static char * hextocstr(apr_byte_t *org, char *dst, int n)
{
char *os = dst;
apr_byte_t v;
static char zitohex[] = "0123456789ABCDEF";
while (--n >= 0) {
v = *org++;
*dst++ = zitohex[v >> 4];
*dst++ = zitohex[v & 0x0f];
}
*dst = 0;
return (os);
}
/**
* Compute the MD5 of org and (if not null org2) string
*
* @param org First String to compute MD5 from
* @param org2 Second String to compute MD5 from (if null no action)
* @param dst Destination MD5 Hex CString
* @return APR_SUCCESS or error
*/
apr_status_t comp_md5(char *org, char *org2, char *dst)
{
apr_md5_ctx_t ctx;
unsigned char buf[AJP14_MD5_DIGESTSIZE + 1];
apr_md5_init(&ctx);
apr_md5_update(&ctx, org, (apr_size_t)strlen(org));
if (org2 != NULL)
apr_md5_update(&ctx, org2, (apr_size_t)strlen(org2));
apr_md5_final(buf, &ctx);
hextocstr(buf, dst, AJP14_MD5_DIGESTSIZE);
return APR_SUCCESS;
}
/**
* Decode the Incoming Login Command and build reply
*
* @param msg AJP Message to be decoded and then filled
* @param secret secret string to be used in logon phase
* @param servername local server name (ie: Apache 2.0.50)
* @return APR_SUCCESS or error
*/
apr_status_t ajp_handle_login(ajp_msg_t *msg, char *secret, char *servername)
{
int status;
char *entropy;
char computedKey[AJP14_COMPUTED_KEY_LEN];
status = ajp_msg_get_string(msg, &entropy);
if (status != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"ajp_handle_login(): can't get seed");
return AJP_ELOGFAIL;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
"ajp_handle_login(): received entropy %s",
entropy);
comp_md5(entropy, secret, computedKey);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
"ajp_handle_login(): computed md5 (%s/%s) -> (%s)",
entropy, secret, computedKey);
ajp_msg_reset(msg);
/* LOGCOMP CMD */
status = ajp_msg_append_uint8(msg, AJP14_LOGCOMP_CMD);
if (status != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"ajp_handle_login(): can't log command");
return AJP_ELOGFAIL;
}
/* COMPUTED-SEED */
status = ajp_msg_append_string(msg, computedKey);
if (status != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"ajp_handle_login(): can't serialize computed secret");
return AJP_ELOGFAIL;
}
/* NEGOCIATION OPTION */
status = ajp_msg_append_uint32(msg, AJP14_CONTEXT_INFO_NEG | AJP14_PROTO_SUPPORT_AJP14_NEG);
if (status != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"ajp_handle_login(): can't append negociation header");
return AJP_ELOGFAIL;
}
/* SERVER NAME */
status = ajp_msg_append_string(msg, servername);
if (status != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"ajp_handle_login(): can't serialize server name");
return AJP_ELOGFAIL;
}
return APR_SUCCESS;
}
/**
* Decode the LogOk Command. After that we're done, the connection is
* perfect and ready.
*
* @param msg AJP Message to be decoded
* @return APR_SUCCESS or error
*/
apr_status_t ajp_handle_logok(ajp_msg_t *msg)
{
apr_status_t status;
apr_uint32_t negociation;
char *server_name;
status = ajp_msg_get_uint32(msg, &negociation);
if (status != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"ajp_handle_logok(): can't get negociation header");
return AJP_ELOGFAIL;
}
status = ajp_msg_get_string(msg, &server_name);
if (status != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"ajp_handle_logok(): can't get servlet engine name");
return AJP_ELOGFAIL;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
"ajp_handle_logok(): Successfully logged to %s",
server_name);
return APR_SUCCESS;
}
/**
* Decode the Log Nok Command
*
* @param msg AJP Message to be decoded
*/
apr_status_t ajp_handle_lognok(ajp_msg_t *msg)
{
apr_status_t status;
apr_uint32_t failurecode;
status = ajp_msg_get_uint32(msg, &failurecode);
if (status != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"ajp_handle_lognok(): can't get failure code");
return AJP_ELOGFAIL;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
"ajp_handle_logok(): logon failure code is %08lx",
(long)failurecode);
return APR_SUCCESS;
}