mech-rpa.c revision 4ac5448461b63de9637de839fbc611a3d503287c
/*
* Compuserve RPA authentication mechanism.
*
* Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
*
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "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 {
struct auth_request auth_request;
int phase;
/* cached: */
unsigned char pwd_md5[16];
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;
unsigned char *session_key;
};
#define RPA_SCHALLENGE_LEN 32
#define RPA_UCHALLENGE_LEN 16
#define RPA_TIMESTAMP_LEN 14
#define ASN1_APPLICATION 0x60
/* 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 *digest)
{
struct md5_context ctx;
unsigned char z[48];
memset(z, 0, sizeof(z));
md5_update(&ctx, z, sizeof(z));
}
/*
* Compute server -> client authentication response.
*/
unsigned char *digest)
{
struct md5_context ctx;
unsigned char tmp[16];
unsigned char z[48];
int i;
memset(z, 0, sizeof(z));
md5_update(&ctx, z, sizeof(z));
for (i = 0; i < 16; 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) {
unsigned int nbytes = *p++ & 0x7f;
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 int
{
const unsigned char *p;
unsigned int version_lo, version_hi;
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 int
{
const unsigned char *p;
unsigned int len;
const char *user;
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;
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 const unsigned char *
{
unsigned int realms_len;
unsigned int length;
/* 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 *
{
unsigned char server_response[16];
/* Generate random session key */
/* Server authentication response */
/* Status, 0 - success */
buffer_append_c(buf, 0);
return buffer_free_without_data(buf);
}
const char *credentials)
{
unsigned char response[16];
}
static void
const char *credentials,
struct auth_request *auth_request)
{
struct rpa_auth_request *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 *request =
(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 *request =
(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 *request =
(struct rpa_auth_request *)auth_request;
case 0:
break;
case 1:
break;
case 2:
break;
default:
break;
}
}
static void
{
if (data_size == 0) {
NULL, 0);
} else {
}
}
static void
{
struct rpa_auth_request *request =
(struct rpa_auth_request *)auth_request;
}
static struct auth_request *mech_rpa_auth_new(void)
{
struct rpa_auth_request *request;
return &request->auth_request;
}
const struct mech_module mech_rpa = {
"RPA",
};