Здравствуйте!
У меня такая проблема: надо в своё приложение вставить простой сервер 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 у меня с отладкой проблемы :( Заранее благодарю.