2
* This file is part of libESMTP, a library for submission of RFC 2822
3
* formatted electronic mail messages using the SMTP protocol described
6
* Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net>
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31
#include <sys/types.h>
33
#include "auth-client.h"
34
#include "auth-plugin.h"
36
#define NELT(x) (sizeof x / sizeof x[0])
38
static int crammd5_init (void *pctx);
39
static void crammd5_destroy (void *ctx);
40
static const char *crammd5_response (void *ctx,
41
const char *challenge, int *len,
42
auth_interact_t interact, void *arg);
44
const struct auth_client_plugin sasl_client =
46
/* Plugin information */
48
"Challenge-Response Authentication Mechanism (RFC 2195)",
61
static const struct auth_client_request client_request[] =
63
{ "user", AUTH_CLEARTEXT | AUTH_USER, "User Name", 0, },
64
{ "passphrase", AUTH_PASS, "Pass Phrase", 0, },
67
struct crammd5_context
75
crammd5_init (void *pctx)
77
struct crammd5_context *context;
79
context = malloc (sizeof (struct crammd5_context));
80
memset (context, 0, sizeof (struct crammd5_context));
82
*(void **) pctx = context;
87
crammd5_destroy (void *ctx)
89
struct crammd5_context *context = ctx;
91
if (context->response != NULL)
93
memset (context->response, 0, context->response_len);
94
free (context->response);
100
crammd5_response (void *ctx, const char *challenge, int *len,
101
auth_interact_t interact, void *arg)
103
struct crammd5_context *context = ctx;
104
char *result[NELT (client_request)];
105
unsigned char digest[16];
109
static const char hex[] = "0123456789abcdef";
111
switch (context->state)
113
case 0: /* No initial response */
118
case 1: /* Digest the challenge and compute a response. */
119
if (!(*interact) (client_request, result, NELT (client_request), arg))
121
hmac_md5 (challenge, *len, result[1], strlen (result[1]), digest);
122
response_len = strlen (result[0]) + 1 + 2 * sizeof digest;
123
response = malloc (response_len);
124
strcpy (response, result[0]);
125
strcat (response, " ");
126
p = strchr (response, '\0');
127
for (i = 0; i < sizeof digest; i++)
129
*p++ = hex[(digest[i] >> 4) & 0x0F];
130
*p++ = hex[digest[i] & 0x0F];
132
/* Note no \0 termination */
134
context->response = response;
135
context->response_len = response_len;