/*
* Compuserve RPA authentication mechanism.
*
* Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
*
* This software is released under the MIT license.
*/
#include "auth-common.h"
#include "mech.h"
#include "passdb.h"
#include "str.h"
#include "strfuncs.h"
#include "safe-memset.h"
#include "randgen.h"
#include "buffer.h"
#include "hostpid.h"
#include "hex-binary.h"
#include "md5.h"
struct rpa_auth_request {
int phase;
/* cached: */
const unsigned char *service_ucs2be;
const unsigned char *username_ucs2be;
const unsigned char *realm_ucs2be;
/* requested: */
unsigned char *service_challenge;
unsigned char *service_timestamp;
/* received: */
unsigned int user_challenge_len;
unsigned char *user_challenge;
unsigned char *user_response;
};
/* Object id encoded using ASN.1 DER */
static const unsigned char rpa_oid[] = {
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x73, 0x01, 0x01
};
/*
* Compute client -> server authentication response.
*/
{
unsigned char z[48];
memset(z, 0, sizeof(z));
md5_update(&ctx, z, sizeof(z));
}
/*
* Compute server -> client authentication response.
*/
{
unsigned char z[48];
unsigned int i;
memset(z, 0, sizeof(z));
md5_update(&ctx, z, sizeof(z));
for (i = 0; i < sizeof(tmp); i++)
md5_update(&ctx, z, sizeof(z));
}
static const unsigned char *
const char **error)
{
const unsigned char *p = data;
unsigned int len = 0;
if (p + 2 > end) {
*error = "message too short";
return NULL;
}
if (*p++ != ASN1_APPLICATION) {
*error = "invalid data type";
return NULL;
}
if ((*p & 0x80) != 0) {
while (nbytes-- > 0) {
if (p >= end) {
*error = "invalid structure length";
return NULL;
}
}
} else
len = *p++;
*error = "structure length disagrees with data size";
return NULL;
}
*error = "not enough space for object id";
return NULL;
}
*error = "invalid object id";
return NULL;
}
return p + sizeof(rpa_oid);
}
static bool
{
const unsigned char *p;
if (p == NULL)
return FALSE;
if (p + 6 > end) {
*error = "message too short";
return FALSE;
}
*error = "protocol version mismatch";
return FALSE;
}
p += 4;
if ((p[0] != 0) || (p[1] != 1)) {
*error = "invalid message flags";
return FALSE;
}
p += 2;
if (p != end) {
*error = "unneeded data found";
return FALSE;
}
return TRUE;
}
static unsigned int
{
const unsigned char *p = *data;
unsigned int len;
if (p > end)
return 0;
len = *p++;
return 0;
return len;
}
static bool
{
const unsigned char *p;
unsigned int len;
if (p == NULL)
return FALSE;
/* Read username@realm */
if (p + 2 > end) {
*error = "message too short";
return FALSE;
}
*error = "message too short";
return FALSE;
}
p += 2;
*error = "missing realm";
return FALSE;
}
p += len;
return FALSE;
&request->username_len);
/* Read user challenge */
if (request->user_challenge_len == 0) {
*error = "invalid user challenge";
return FALSE;
}
/* Read user response */
if (len != RPA_UCHALLENGE_LEN) {
*error = "invalid user response";
return FALSE;
}
if (p != end) {
*error = "unneeded data found";
return FALSE;
}
return TRUE;
}
static void
{
if (length < 0x80) {
} else if (length < 0x100) {
} else {
}
}
static void
{
}
static const unsigned char *
{
const char *const *tmp;
}
}
/* Protocol version */
buffer_append_c(buf, 0);
/* Service challenge */
/* Timestamp, looks like clients accept anything we send */
/* Realm list */
return buffer_free_without_data(&buf);
}
static const unsigned char *
{
sizeof(server_response) + 1 +
/* Generate random session key */
/* Server authentication response */
/* Status, 0 - success */
buffer_append_c(buf, 0);
return buffer_free_without_data(&buf);
}
{
"invalid credentials length");
return FALSE;
}
}
static void
struct auth_request *auth_request)
{
(struct rpa_auth_request *)auth_request;
const unsigned char *token4;
switch (result) {
case PASSDB_RESULT_OK:
else {
}
break;
break;
default:
break;
}
}
static void
{
(struct rpa_auth_request *)auth_request;
const unsigned char *token2;
"invalid token 1: %s", error);
return;
}
&request->service_len);
}
static void
{
(struct rpa_auth_request *)auth_request;
const char *error;
"invalid token 3: %s", error);
return;
}
}
static void
{
if ((data_size != sizeof(client_ack)) ||
"invalid token 5 or client rejects us");
} else {
}
}
static void
{
(struct rpa_auth_request *)auth_request;
case 0:
break;
case 1:
break;
case 2:
break;
default:
break;
}
}
static void
{
(struct rpa_auth_request *)auth_request;
}
{
return &request->auth_request;
}
"RPA",
};