Здравствуйте!
У меня такая проблема: надо в своё приложение вставить простой сервер RADIUS-Accounting. На данном этапе я не могу сформировать понятный клиенту отклик Access-Reject (клиент на своей строне пишет "No answer from server"). Насколько я понял, согласно rfc2865, отклик Access-Reject может не содержать никаких атрибутов и поле Responce Authentificator вычисляется по формуле:
ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret), где +
подразумевает конкатенацию строк.
Я так и делал, но нифига не получалось. Тогда я начал пытаться списывать код у проектов GNU RADIUS, FreeRADIUS и т.п. Та же картина. Вот мой код:
[CODE]
.....
void MD5Calc(unsigned char *output, unsigned char *input,
unsigned int inlen)
{
MD5_CTX context;
MD5Init(&context);
MD5Update(&context, input, inlen);
MD5Final(output, &context);
}
.....
#pragma pack (push, 1)
struct TRadiusPacket
{
byte code;
byte identifier;
unsigned short length;
byte auth[AUTH_VECTOR_LEN];
byte *attribute; // 4096-20 max
};
struct AUTH_HDR
{
byte code;
byte id;
unsigned short length;
byte vector[AUTH_VECTOR_LEN];
byte data[2];
};
#pragma pack(pop)
.....
/*
Имя: prepare_access_responce
Назначение: Формирование отклика на запрос Access-Request
Параметры: code - код отклика
access_request - тело запроса Access-Request
shared_secret - Так называемый "Shared secret" протокола RADIUS
output - сформированный отклик.
При этом память под отклик уже должна быть выделена извне функции
*/
byte *
prepare_access_responce( byte code, TRadiusPacket * access_request,
const char * shared_secret, byte * output )
{
/*
Это уже проверялось - не работает
unsigned short length = htons(4 + AUTH_VECTOR_LEN);
output[0] = code;
output[1] = access_request->identifier;
memcpy( output + 2, (byte *)&length, 2 );
memset ( output + 4, 0, AUTH_VECTOR_LEN );
unsigned long secret_len = strlen( shared_secret );
byte digest[16];
MD5CalcDigest( output, length, shared_secret, secret_len, digest);
memcpy( output + 4, digest, 16 );
*/
/*
// Из проекта GNU Radius 1.3, файл cryptpass.c, функция grad_encrypt_text()
// с моими изменениями и добавлениями
byte digest[AUTH_VECTOR_LEN];
int secretlen = strlen( shared_secret );
int md5len = secretlen + AUTH_VECTOR_LEN;
byte * md5buf = new byte [md5len];
memcpy( md5buf, shared_secret, secretlen );
memcpy( md5buf + secretlen, access_request->auth, AUTH_VECTOR_LEN );
MD5Calc( digest, md5buf, md5len );
// Отсебятина:
memcpy( output + 4, digest, AUTH_VECTOR_LEN );
output[0] = code;
output[1] = access_request->identifier;
unsigned short length = MIN_PACKET_SIZE;
memcpy( output + 2, (byte *)&length, 2 );
*/
// Опять-же код из проекта GNU-RADIUS v. 0.9.6, файл radiusd/radius.c однако :-)
// Естественно, с моими изменениями и дополнениями.
byte digest[AUTH_DIGEST_LEN];
byte send_buffer[MAX_PACKET_SIZE] = {'\0'};
AUTH_HDR *auth = (AUTH_HDR *)send_buffer;
auth->code = code;
auth->id = access_request->identifier;
memcpy(auth->vector, access_request->auth, AUTH_VECTOR_LEN);
unsigned short total_length = AUTH_HDR_LEN;
auth->length = htons(total_length);
// Append secret and calculate the response digest
int secretlen = strlen ( shared_secret );
memcpy(send_buffer + total_length, shared_secret, secretlen);
MD5Calc( digest, (byte *)auth, total_length + secretlen);
memcpy(auth->vector, digest, AUTH_VECTOR_LEN);
memset(send_buffer + total_length, 0, secretlen);
memcpy( output, (byte *)auth, total_length );
return output;
}
[/CODE]
Пока отлаживаюсь под Windows, так как под Linux у меня с отладкой проблемы :(
Заранее благодарю.