]> git.ozlabs.org Git - ppp.git/blob - pppd/chap-md5.c
PPPoE updates: don't exit if discovery fails, cope with both
[ppp.git] / pppd / chap-md5.c
1 /*
2  * chap-md5.c - New CHAP/MD5 implementation.
3  *
4  * Copyright (c) 2003 Paul Mackerras. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. The name(s) of the authors of this software must not be used to
19  *    endorse or promote products derived from this software without
20  *    prior written permission.
21  *
22  * 4. Redistributions of any form whatsoever must retain the following
23  *    acknowledgment:
24  *    "This product includes software developed by Paul Mackerras
25  *     <paulus@samba.org>".
26  *
27  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
28  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
29  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
30  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
31  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
32  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
33  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34  */
35
36 #define RCSID   "$Id: chap-md5.c,v 1.2 2003/11/27 22:21:46 paulus Exp $"
37
38 #include <stdlib.h>
39 #include <string.h>
40 #include "pppd.h"
41 #include "chap-new.h"
42 #include "chap-md5.h"
43 #include "magic.h"
44 #include "md5.h"
45
46 #define MD5_HASH_SIZE           16
47 #define MD5_MIN_CHALLENGE       16
48 #define MD5_MAX_CHALLENGE       24
49
50 static void
51 chap_md5_generate_challenge(unsigned char *cp)
52 {
53         int clen;
54
55         clen = (int)(drand48() * (MD5_MAX_CHALLENGE - MD5_MIN_CHALLENGE))
56                 + MD5_MIN_CHALLENGE;
57         *cp++ = clen;
58         random_bytes(cp, clen);
59 }
60
61 static int
62 chap_md5_verify_response(int id, char *name,
63                          unsigned char *secret, int secret_len,
64                          unsigned char *challenge, unsigned char *response,
65                          char *message, int message_space)
66 {
67         MD5_CTX ctx;
68         unsigned char idbyte = id;
69         unsigned char hash[MD5_HASH_SIZE];
70         int challenge_len, response_len;
71
72         challenge_len = *challenge++;
73         response_len = *response++;
74         if (response_len == MD5_HASH_SIZE) {
75                 /* Generate hash of ID, secret, challenge */
76                 MD5Init(&ctx);
77                 MD5Update(&ctx, &idbyte, 1);
78                 MD5Update(&ctx, secret, secret_len);
79                 MD5Update(&ctx, challenge, challenge_len);
80                 MD5Final(hash, &ctx);
81
82                 /* Test if our hash matches the peer's response */
83                 if (memcmp(hash, response, MD5_HASH_SIZE) == 0) {
84                         slprintf(message, message_space, "Access granted");
85                         return 1;
86                 }
87         }
88         slprintf(message, message_space, "Access denied");
89         return 0;
90 }
91
92 static void
93 chap_md5_make_response(unsigned char *response, int id, char *our_name,
94                        unsigned char *challenge, char *secret, int secret_len,
95                        unsigned char *private)
96 {
97         MD5_CTX ctx;
98         unsigned char idbyte = id;
99         int challenge_len = *challenge++;
100
101         MD5Init(&ctx);
102         MD5Update(&ctx, &idbyte, 1);
103         MD5Update(&ctx, secret, secret_len);
104         MD5Update(&ctx, challenge, challenge_len);
105         MD5Final(&response[1], &ctx);
106         response[0] = MD5_HASH_SIZE;
107 }
108
109 static struct chap_digest_type md5_digest = {
110         CHAP_MD5,               /* code */
111         chap_md5_generate_challenge,
112         chap_md5_verify_response,
113         chap_md5_make_response,
114         NULL,                   /* check_success */
115         NULL,                   /* handle_failure */
116 };
117
118 void
119 chap_md5_init(void)
120 {
121         chap_register_digest(&md5_digest);
122 }