]> git.ozlabs.org Git - ppp.git/blob - pppd/chap-md5.c
config: Include some extra files in the tarball
[ppp.git] / pppd / chap-md5.c
1 /*
2  * chap-md5.c - New CHAP/MD5 implementation.
3  *
4  * Copyright (c) 2003-2024 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  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
19  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
21  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
23  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
24  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include "pppd-private.h"
34 #include "chap.h"
35 #include "chap-md5.h"
36 #include "magic.h"
37 #include "crypto.h"
38
39 #define MD5_MIN_CHALLENGE       16
40 #define MD5_MAX_CHALLENGE       24
41
42 static void
43 chap_md5_generate_challenge(unsigned char *cp)
44 {
45         int clen;
46
47         clen = (int)(drand48() * (MD5_MAX_CHALLENGE - MD5_MIN_CHALLENGE))
48                 + MD5_MIN_CHALLENGE;
49         *cp++ = clen;
50         random_bytes(cp, clen);
51 }
52
53 static int
54 chap_md5_verify_response(int id, char *name,
55                          unsigned char *secret, int secret_len,
56                          unsigned char *challenge, unsigned char *response,
57                          char *message, int message_space)
58 {
59         unsigned char idbyte = id;
60         unsigned char hash[MD5_DIGEST_LENGTH];
61         unsigned int  hash_len = MD5_DIGEST_LENGTH;
62         int challenge_len, response_len;
63         bool success = 0;
64
65         challenge_len = *challenge++;
66         response_len = *response++;
67         if (response_len == MD5_DIGEST_LENGTH) {
68
69                 /* Generate hash of ID, secret, challenge */
70                 PPP_MD_CTX* ctx = PPP_MD_CTX_new();
71                 if (ctx) {
72
73                         if (PPP_DigestInit(ctx, PPP_md5())) {
74
75                                 if (PPP_DigestUpdate(ctx, &idbyte, 1)) {
76
77                                         if (PPP_DigestUpdate(ctx, secret, secret_len)) {
78
79                                                 if (PPP_DigestUpdate(ctx, challenge, challenge_len)) {
80
81                                                         if (PPP_DigestFinal(ctx, hash, &hash_len)) {
82
83                                                                 success = 1;
84                                                         }
85                                                 }
86                                         }
87                                 }
88                         }
89                         PPP_MD_CTX_free(ctx);
90                 }
91         }
92         if (success && memcmp(hash, response, hash_len) == 0) {
93                 slprintf(message, message_space, "Access granted");
94                 return 1;
95         }
96         slprintf(message, message_space, "Access denied");
97         return 0;
98 }
99
100 static void
101 chap_md5_make_response(unsigned char *response, int id, char *our_name,
102                        unsigned char *challenge, char *secret, int secret_len,
103                        unsigned char *private)
104 {
105         unsigned char idbyte = id;
106         int challenge_len = *challenge++;
107         int hash_len = MD5_DIGEST_LENGTH;
108
109         response[0] = 0;
110         PPP_MD_CTX* ctx = PPP_MD_CTX_new();
111         if (ctx) {
112
113                 if (PPP_DigestInit(ctx, PPP_md5())) {
114
115                         if (PPP_DigestUpdate(ctx, &idbyte, 1)) {
116
117                                 if (PPP_DigestUpdate(ctx, secret, secret_len)) {
118
119                                         if (PPP_DigestUpdate(ctx, challenge, challenge_len)) {
120
121                                                 if (PPP_DigestFinal(ctx, &response[1], &hash_len)) {
122
123                                                         response[0] = hash_len;
124                                                 }
125                                         }
126                                 }
127                         }
128                 }
129                 PPP_MD_CTX_free(ctx);
130         }
131         if (response[0] == 0)
132                 warn("Error occurred in preparing CHAP-Response");
133 }
134
135 static struct chap_digest_type md5_digest = {
136         CHAP_MD5,               /* code */
137         chap_md5_generate_challenge,
138         chap_md5_verify_response,
139         chap_md5_make_response,
140         NULL,                   /* check_success */
141         NULL,                   /* handle_failure */
142 };
143
144 void
145 chap_md5_init(void)
146 {
147         chap_register_digest(&md5_digest);
148 }