LwIP with PPP & Ethernet integration

Dependents:   NetworkingCoreLib

This is the mbed port of the LwIP stack: http://savannah.nongnu.org/projects/lwip/

It includes contributed content from NXP's port for LPCxxxx devices: http://www.lpcware.com/content/project/lightweight-ip-lwip-networking-stack

Licence

LwIP is licenced under the BSD licence:

Copyright (c) 2001-2004 Swedish Institute of Computer Science. 
All rights reserved. 
Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met: 
1. Redistributions of source code must retain the above copyright notice, 
this list of conditions and the following disclaimer. 
2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution. 
3. The name of the author may not be used to endorse or promote products 
derived from this software without specific prior written permission. 
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
donatien
Date:
Thu May 24 15:53:48 2012 +0000
Revision:
0:8e01dca41002
Merge with Emilio's LwIp

Who changed what in which revision?

UserRevisionLine numberNew contents of line
donatien 0:8e01dca41002 1 /*** WARNING - THIS HAS NEVER BEEN FINISHED ***/
donatien 0:8e01dca41002 2 /*****************************************************************************
donatien 0:8e01dca41002 3 * chap.c - Network Challenge Handshake Authentication Protocol program file.
donatien 0:8e01dca41002 4 *
donatien 0:8e01dca41002 5 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
donatien 0:8e01dca41002 6 * portions Copyright (c) 1997 by Global Election Systems Inc.
donatien 0:8e01dca41002 7 *
donatien 0:8e01dca41002 8 * The authors hereby grant permission to use, copy, modify, distribute,
donatien 0:8e01dca41002 9 * and license this software and its documentation for any purpose, provided
donatien 0:8e01dca41002 10 * that existing copyright notices are retained in all copies and that this
donatien 0:8e01dca41002 11 * notice and the following disclaimer are included verbatim in any
donatien 0:8e01dca41002 12 * distributions. No written agreement, license, or royalty fee is required
donatien 0:8e01dca41002 13 * for any of the authorized uses.
donatien 0:8e01dca41002 14 *
donatien 0:8e01dca41002 15 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
donatien 0:8e01dca41002 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
donatien 0:8e01dca41002 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
donatien 0:8e01dca41002 18 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
donatien 0:8e01dca41002 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
donatien 0:8e01dca41002 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
donatien 0:8e01dca41002 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
donatien 0:8e01dca41002 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
donatien 0:8e01dca41002 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
donatien 0:8e01dca41002 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
donatien 0:8e01dca41002 25 *
donatien 0:8e01dca41002 26 ******************************************************************************
donatien 0:8e01dca41002 27 * REVISION HISTORY
donatien 0:8e01dca41002 28 *
donatien 0:8e01dca41002 29 * 03-01-01 Marc Boucher <marc@mbsi.ca>
donatien 0:8e01dca41002 30 * Ported to lwIP.
donatien 0:8e01dca41002 31 * 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
donatien 0:8e01dca41002 32 * Original based on BSD chap.c.
donatien 0:8e01dca41002 33 *****************************************************************************/
donatien 0:8e01dca41002 34 /*
donatien 0:8e01dca41002 35 * chap.c - Challenge Handshake Authentication Protocol.
donatien 0:8e01dca41002 36 *
donatien 0:8e01dca41002 37 * Copyright (c) 1993 The Australian National University.
donatien 0:8e01dca41002 38 * All rights reserved.
donatien 0:8e01dca41002 39 *
donatien 0:8e01dca41002 40 * Redistribution and use in source and binary forms are permitted
donatien 0:8e01dca41002 41 * provided that the above copyright notice and this paragraph are
donatien 0:8e01dca41002 42 * duplicated in all such forms and that any documentation,
donatien 0:8e01dca41002 43 * advertising materials, and other materials related to such
donatien 0:8e01dca41002 44 * distribution and use acknowledge that the software was developed
donatien 0:8e01dca41002 45 * by the Australian National University. The name of the University
donatien 0:8e01dca41002 46 * may not be used to endorse or promote products derived from this
donatien 0:8e01dca41002 47 * software without specific prior written permission.
donatien 0:8e01dca41002 48 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
donatien 0:8e01dca41002 49 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
donatien 0:8e01dca41002 50 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
donatien 0:8e01dca41002 51 *
donatien 0:8e01dca41002 52 * Copyright (c) 1991 Gregory M. Christy.
donatien 0:8e01dca41002 53 * All rights reserved.
donatien 0:8e01dca41002 54 *
donatien 0:8e01dca41002 55 * Redistribution and use in source and binary forms are permitted
donatien 0:8e01dca41002 56 * provided that the above copyright notice and this paragraph are
donatien 0:8e01dca41002 57 * duplicated in all such forms and that any documentation,
donatien 0:8e01dca41002 58 * advertising materials, and other materials related to such
donatien 0:8e01dca41002 59 * distribution and use acknowledge that the software was developed
donatien 0:8e01dca41002 60 * by Gregory M. Christy. The name of the author may not be used to
donatien 0:8e01dca41002 61 * endorse or promote products derived from this software without
donatien 0:8e01dca41002 62 * specific prior written permission.
donatien 0:8e01dca41002 63 *
donatien 0:8e01dca41002 64 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
donatien 0:8e01dca41002 65 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
donatien 0:8e01dca41002 66 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
donatien 0:8e01dca41002 67 */
donatien 0:8e01dca41002 68
donatien 0:8e01dca41002 69 #include "lwip/opt.h"
donatien 0:8e01dca41002 70
donatien 0:8e01dca41002 71 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
donatien 0:8e01dca41002 72
donatien 0:8e01dca41002 73 #if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
donatien 0:8e01dca41002 74
donatien 0:8e01dca41002 75 #include "ppp.h"
donatien 0:8e01dca41002 76 #include "pppdebug.h"
donatien 0:8e01dca41002 77
donatien 0:8e01dca41002 78 #include "magic.h"
donatien 0:8e01dca41002 79 #include "randm.h"
donatien 0:8e01dca41002 80 #include "auth.h"
donatien 0:8e01dca41002 81 #include "md5.h"
donatien 0:8e01dca41002 82 #include "chap.h"
donatien 0:8e01dca41002 83 #include "chpms.h"
donatien 0:8e01dca41002 84
donatien 0:8e01dca41002 85 #include <string.h>
donatien 0:8e01dca41002 86
donatien 0:8e01dca41002 87 #if 0 /* UNUSED */
donatien 0:8e01dca41002 88 /*
donatien 0:8e01dca41002 89 * Command-line options.
donatien 0:8e01dca41002 90 */
donatien 0:8e01dca41002 91 static option_t chap_option_list[] = {
donatien 0:8e01dca41002 92 { "chap-restart", o_int, &chap[0].timeouttime,
donatien 0:8e01dca41002 93 "Set timeout for CHAP" },
donatien 0:8e01dca41002 94 { "chap-max-challenge", o_int, &chap[0].max_transmits,
donatien 0:8e01dca41002 95 "Set max #xmits for challenge" },
donatien 0:8e01dca41002 96 { "chap-interval", o_int, &chap[0].chal_interval,
donatien 0:8e01dca41002 97 "Set interval for rechallenge" },
donatien 0:8e01dca41002 98 #ifdef MSLANMAN
donatien 0:8e01dca41002 99 { "ms-lanman", o_bool, &ms_lanman,
donatien 0:8e01dca41002 100 "Use LanMan passwd when using MS-CHAP", 1 },
donatien 0:8e01dca41002 101 #endif
donatien 0:8e01dca41002 102 { NULL }
donatien 0:8e01dca41002 103 };
donatien 0:8e01dca41002 104 #endif /* UNUSED */
donatien 0:8e01dca41002 105
donatien 0:8e01dca41002 106 /*
donatien 0:8e01dca41002 107 * Protocol entry points.
donatien 0:8e01dca41002 108 */
donatien 0:8e01dca41002 109 static void ChapInit (int);
donatien 0:8e01dca41002 110 static void ChapLowerUp (int);
donatien 0:8e01dca41002 111 static void ChapLowerDown (int);
donatien 0:8e01dca41002 112 static void ChapInput (int, u_char *, int);
donatien 0:8e01dca41002 113 static void ChapProtocolReject (int);
donatien 0:8e01dca41002 114 #if PPP_ADDITIONAL_CALLBACKS
donatien 0:8e01dca41002 115 static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *);
donatien 0:8e01dca41002 116 #endif
donatien 0:8e01dca41002 117
donatien 0:8e01dca41002 118 struct protent chap_protent = {
donatien 0:8e01dca41002 119 PPP_CHAP,
donatien 0:8e01dca41002 120 ChapInit,
donatien 0:8e01dca41002 121 ChapInput,
donatien 0:8e01dca41002 122 ChapProtocolReject,
donatien 0:8e01dca41002 123 ChapLowerUp,
donatien 0:8e01dca41002 124 ChapLowerDown,
donatien 0:8e01dca41002 125 NULL,
donatien 0:8e01dca41002 126 NULL,
donatien 0:8e01dca41002 127 #if PPP_ADDITIONAL_CALLBACKS
donatien 0:8e01dca41002 128 ChapPrintPkt,
donatien 0:8e01dca41002 129 NULL,
donatien 0:8e01dca41002 130 #endif /* PPP_ADDITIONAL_CALLBACKS */
donatien 0:8e01dca41002 131 1,
donatien 0:8e01dca41002 132 "CHAP",
donatien 0:8e01dca41002 133 #if PPP_ADDITIONAL_CALLBACKS
donatien 0:8e01dca41002 134 NULL,
donatien 0:8e01dca41002 135 NULL,
donatien 0:8e01dca41002 136 NULL
donatien 0:8e01dca41002 137 #endif /* PPP_ADDITIONAL_CALLBACKS */
donatien 0:8e01dca41002 138 };
donatien 0:8e01dca41002 139
donatien 0:8e01dca41002 140 chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
donatien 0:8e01dca41002 141
donatien 0:8e01dca41002 142 static void ChapChallengeTimeout (void *);
donatien 0:8e01dca41002 143 static void ChapResponseTimeout (void *);
donatien 0:8e01dca41002 144 static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int);
donatien 0:8e01dca41002 145 static void ChapRechallenge (void *);
donatien 0:8e01dca41002 146 static void ChapReceiveResponse (chap_state *, u_char *, int, int);
donatien 0:8e01dca41002 147 static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
donatien 0:8e01dca41002 148 static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
donatien 0:8e01dca41002 149 static void ChapSendStatus (chap_state *, int);
donatien 0:8e01dca41002 150 static void ChapSendChallenge (chap_state *);
donatien 0:8e01dca41002 151 static void ChapSendResponse (chap_state *);
donatien 0:8e01dca41002 152 static void ChapGenChallenge (chap_state *);
donatien 0:8e01dca41002 153
donatien 0:8e01dca41002 154 /*
donatien 0:8e01dca41002 155 * ChapInit - Initialize a CHAP unit.
donatien 0:8e01dca41002 156 */
donatien 0:8e01dca41002 157 static void
donatien 0:8e01dca41002 158 ChapInit(int unit)
donatien 0:8e01dca41002 159 {
donatien 0:8e01dca41002 160 chap_state *cstate = &chap[unit];
donatien 0:8e01dca41002 161
donatien 0:8e01dca41002 162 BZERO(cstate, sizeof(*cstate));
donatien 0:8e01dca41002 163 cstate->unit = unit;
donatien 0:8e01dca41002 164 cstate->clientstate = CHAPCS_INITIAL;
donatien 0:8e01dca41002 165 cstate->serverstate = CHAPSS_INITIAL;
donatien 0:8e01dca41002 166 cstate->timeouttime = CHAP_DEFTIMEOUT;
donatien 0:8e01dca41002 167 cstate->max_transmits = CHAP_DEFTRANSMITS;
donatien 0:8e01dca41002 168 /* random number generator is initialized in magic_init */
donatien 0:8e01dca41002 169 }
donatien 0:8e01dca41002 170
donatien 0:8e01dca41002 171
donatien 0:8e01dca41002 172 /*
donatien 0:8e01dca41002 173 * ChapAuthWithPeer - Authenticate us with our peer (start client).
donatien 0:8e01dca41002 174 *
donatien 0:8e01dca41002 175 */
donatien 0:8e01dca41002 176 void
donatien 0:8e01dca41002 177 ChapAuthWithPeer(int unit, char *our_name, u_char digest)
donatien 0:8e01dca41002 178 {
donatien 0:8e01dca41002 179 chap_state *cstate = &chap[unit];
donatien 0:8e01dca41002 180
donatien 0:8e01dca41002 181 cstate->resp_name = our_name;
donatien 0:8e01dca41002 182 cstate->resp_type = digest;
donatien 0:8e01dca41002 183
donatien 0:8e01dca41002 184 if (cstate->clientstate == CHAPCS_INITIAL ||
donatien 0:8e01dca41002 185 cstate->clientstate == CHAPCS_PENDING) {
donatien 0:8e01dca41002 186 /* lower layer isn't up - wait until later */
donatien 0:8e01dca41002 187 cstate->clientstate = CHAPCS_PENDING;
donatien 0:8e01dca41002 188 return;
donatien 0:8e01dca41002 189 }
donatien 0:8e01dca41002 190
donatien 0:8e01dca41002 191 /*
donatien 0:8e01dca41002 192 * We get here as a result of LCP coming up.
donatien 0:8e01dca41002 193 * So even if CHAP was open before, we will
donatien 0:8e01dca41002 194 * have to re-authenticate ourselves.
donatien 0:8e01dca41002 195 */
donatien 0:8e01dca41002 196 cstate->clientstate = CHAPCS_LISTEN;
donatien 0:8e01dca41002 197 }
donatien 0:8e01dca41002 198
donatien 0:8e01dca41002 199
donatien 0:8e01dca41002 200 /*
donatien 0:8e01dca41002 201 * ChapAuthPeer - Authenticate our peer (start server).
donatien 0:8e01dca41002 202 */
donatien 0:8e01dca41002 203 void
donatien 0:8e01dca41002 204 ChapAuthPeer(int unit, char *our_name, u_char digest)
donatien 0:8e01dca41002 205 {
donatien 0:8e01dca41002 206 chap_state *cstate = &chap[unit];
donatien 0:8e01dca41002 207
donatien 0:8e01dca41002 208 cstate->chal_name = our_name;
donatien 0:8e01dca41002 209 cstate->chal_type = digest;
donatien 0:8e01dca41002 210
donatien 0:8e01dca41002 211 if (cstate->serverstate == CHAPSS_INITIAL ||
donatien 0:8e01dca41002 212 cstate->serverstate == CHAPSS_PENDING) {
donatien 0:8e01dca41002 213 /* lower layer isn't up - wait until later */
donatien 0:8e01dca41002 214 cstate->serverstate = CHAPSS_PENDING;
donatien 0:8e01dca41002 215 return;
donatien 0:8e01dca41002 216 }
donatien 0:8e01dca41002 217
donatien 0:8e01dca41002 218 ChapGenChallenge(cstate);
donatien 0:8e01dca41002 219 ChapSendChallenge(cstate); /* crank it up dude! */
donatien 0:8e01dca41002 220 cstate->serverstate = CHAPSS_INITIAL_CHAL;
donatien 0:8e01dca41002 221 }
donatien 0:8e01dca41002 222
donatien 0:8e01dca41002 223
donatien 0:8e01dca41002 224 /*
donatien 0:8e01dca41002 225 * ChapChallengeTimeout - Timeout expired on sending challenge.
donatien 0:8e01dca41002 226 */
donatien 0:8e01dca41002 227 static void
donatien 0:8e01dca41002 228 ChapChallengeTimeout(void *arg)
donatien 0:8e01dca41002 229 {
donatien 0:8e01dca41002 230 chap_state *cstate = (chap_state *) arg;
donatien 0:8e01dca41002 231
donatien 0:8e01dca41002 232 /* if we aren't sending challenges, don't worry. then again we */
donatien 0:8e01dca41002 233 /* probably shouldn't be here either */
donatien 0:8e01dca41002 234 if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
donatien 0:8e01dca41002 235 cstate->serverstate != CHAPSS_RECHALLENGE) {
donatien 0:8e01dca41002 236 return;
donatien 0:8e01dca41002 237 }
donatien 0:8e01dca41002 238
donatien 0:8e01dca41002 239 if (cstate->chal_transmits >= cstate->max_transmits) {
donatien 0:8e01dca41002 240 /* give up on peer */
donatien 0:8e01dca41002 241 CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n"));
donatien 0:8e01dca41002 242 cstate->serverstate = CHAPSS_BADAUTH;
donatien 0:8e01dca41002 243 auth_peer_fail(cstate->unit, PPP_CHAP);
donatien 0:8e01dca41002 244 return;
donatien 0:8e01dca41002 245 }
donatien 0:8e01dca41002 246
donatien 0:8e01dca41002 247 ChapSendChallenge(cstate); /* Re-send challenge */
donatien 0:8e01dca41002 248 }
donatien 0:8e01dca41002 249
donatien 0:8e01dca41002 250
donatien 0:8e01dca41002 251 /*
donatien 0:8e01dca41002 252 * ChapResponseTimeout - Timeout expired on sending response.
donatien 0:8e01dca41002 253 */
donatien 0:8e01dca41002 254 static void
donatien 0:8e01dca41002 255 ChapResponseTimeout(void *arg)
donatien 0:8e01dca41002 256 {
donatien 0:8e01dca41002 257 chap_state *cstate = (chap_state *) arg;
donatien 0:8e01dca41002 258
donatien 0:8e01dca41002 259 /* if we aren't sending a response, don't worry. */
donatien 0:8e01dca41002 260 if (cstate->clientstate != CHAPCS_RESPONSE) {
donatien 0:8e01dca41002 261 return;
donatien 0:8e01dca41002 262 }
donatien 0:8e01dca41002 263
donatien 0:8e01dca41002 264 ChapSendResponse(cstate); /* re-send response */
donatien 0:8e01dca41002 265 }
donatien 0:8e01dca41002 266
donatien 0:8e01dca41002 267
donatien 0:8e01dca41002 268 /*
donatien 0:8e01dca41002 269 * ChapRechallenge - Time to challenge the peer again.
donatien 0:8e01dca41002 270 */
donatien 0:8e01dca41002 271 static void
donatien 0:8e01dca41002 272 ChapRechallenge(void *arg)
donatien 0:8e01dca41002 273 {
donatien 0:8e01dca41002 274 chap_state *cstate = (chap_state *) arg;
donatien 0:8e01dca41002 275
donatien 0:8e01dca41002 276 /* if we aren't sending a response, don't worry. */
donatien 0:8e01dca41002 277 if (cstate->serverstate != CHAPSS_OPEN) {
donatien 0:8e01dca41002 278 return;
donatien 0:8e01dca41002 279 }
donatien 0:8e01dca41002 280
donatien 0:8e01dca41002 281 ChapGenChallenge(cstate);
donatien 0:8e01dca41002 282 ChapSendChallenge(cstate);
donatien 0:8e01dca41002 283 cstate->serverstate = CHAPSS_RECHALLENGE;
donatien 0:8e01dca41002 284 }
donatien 0:8e01dca41002 285
donatien 0:8e01dca41002 286
donatien 0:8e01dca41002 287 /*
donatien 0:8e01dca41002 288 * ChapLowerUp - The lower layer is up.
donatien 0:8e01dca41002 289 *
donatien 0:8e01dca41002 290 * Start up if we have pending requests.
donatien 0:8e01dca41002 291 */
donatien 0:8e01dca41002 292 static void
donatien 0:8e01dca41002 293 ChapLowerUp(int unit)
donatien 0:8e01dca41002 294 {
donatien 0:8e01dca41002 295 chap_state *cstate = &chap[unit];
donatien 0:8e01dca41002 296
donatien 0:8e01dca41002 297 if (cstate->clientstate == CHAPCS_INITIAL) {
donatien 0:8e01dca41002 298 cstate->clientstate = CHAPCS_CLOSED;
donatien 0:8e01dca41002 299 } else if (cstate->clientstate == CHAPCS_PENDING) {
donatien 0:8e01dca41002 300 cstate->clientstate = CHAPCS_LISTEN;
donatien 0:8e01dca41002 301 }
donatien 0:8e01dca41002 302
donatien 0:8e01dca41002 303 if (cstate->serverstate == CHAPSS_INITIAL) {
donatien 0:8e01dca41002 304 cstate->serverstate = CHAPSS_CLOSED;
donatien 0:8e01dca41002 305 } else if (cstate->serverstate == CHAPSS_PENDING) {
donatien 0:8e01dca41002 306 ChapGenChallenge(cstate);
donatien 0:8e01dca41002 307 ChapSendChallenge(cstate);
donatien 0:8e01dca41002 308 cstate->serverstate = CHAPSS_INITIAL_CHAL;
donatien 0:8e01dca41002 309 }
donatien 0:8e01dca41002 310 }
donatien 0:8e01dca41002 311
donatien 0:8e01dca41002 312
donatien 0:8e01dca41002 313 /*
donatien 0:8e01dca41002 314 * ChapLowerDown - The lower layer is down.
donatien 0:8e01dca41002 315 *
donatien 0:8e01dca41002 316 * Cancel all timeouts.
donatien 0:8e01dca41002 317 */
donatien 0:8e01dca41002 318 static void
donatien 0:8e01dca41002 319 ChapLowerDown(int unit)
donatien 0:8e01dca41002 320 {
donatien 0:8e01dca41002 321 chap_state *cstate = &chap[unit];
donatien 0:8e01dca41002 322
donatien 0:8e01dca41002 323 /* Timeout(s) pending? Cancel if so. */
donatien 0:8e01dca41002 324 if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
donatien 0:8e01dca41002 325 cstate->serverstate == CHAPSS_RECHALLENGE) {
donatien 0:8e01dca41002 326 UNTIMEOUT(ChapChallengeTimeout, cstate);
donatien 0:8e01dca41002 327 } else if (cstate->serverstate == CHAPSS_OPEN
donatien 0:8e01dca41002 328 && cstate->chal_interval != 0) {
donatien 0:8e01dca41002 329 UNTIMEOUT(ChapRechallenge, cstate);
donatien 0:8e01dca41002 330 }
donatien 0:8e01dca41002 331 if (cstate->clientstate == CHAPCS_RESPONSE) {
donatien 0:8e01dca41002 332 UNTIMEOUT(ChapResponseTimeout, cstate);
donatien 0:8e01dca41002 333 }
donatien 0:8e01dca41002 334 cstate->clientstate = CHAPCS_INITIAL;
donatien 0:8e01dca41002 335 cstate->serverstate = CHAPSS_INITIAL;
donatien 0:8e01dca41002 336 }
donatien 0:8e01dca41002 337
donatien 0:8e01dca41002 338
donatien 0:8e01dca41002 339 /*
donatien 0:8e01dca41002 340 * ChapProtocolReject - Peer doesn't grok CHAP.
donatien 0:8e01dca41002 341 */
donatien 0:8e01dca41002 342 static void
donatien 0:8e01dca41002 343 ChapProtocolReject(int unit)
donatien 0:8e01dca41002 344 {
donatien 0:8e01dca41002 345 chap_state *cstate = &chap[unit];
donatien 0:8e01dca41002 346
donatien 0:8e01dca41002 347 if (cstate->serverstate != CHAPSS_INITIAL &&
donatien 0:8e01dca41002 348 cstate->serverstate != CHAPSS_CLOSED) {
donatien 0:8e01dca41002 349 auth_peer_fail(unit, PPP_CHAP);
donatien 0:8e01dca41002 350 }
donatien 0:8e01dca41002 351 if (cstate->clientstate != CHAPCS_INITIAL &&
donatien 0:8e01dca41002 352 cstate->clientstate != CHAPCS_CLOSED) {
donatien 0:8e01dca41002 353 auth_withpeer_fail(unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
donatien 0:8e01dca41002 354 }
donatien 0:8e01dca41002 355 ChapLowerDown(unit); /* shutdown chap */
donatien 0:8e01dca41002 356 }
donatien 0:8e01dca41002 357
donatien 0:8e01dca41002 358
donatien 0:8e01dca41002 359 /*
donatien 0:8e01dca41002 360 * ChapInput - Input CHAP packet.
donatien 0:8e01dca41002 361 */
donatien 0:8e01dca41002 362 static void
donatien 0:8e01dca41002 363 ChapInput(int unit, u_char *inpacket, int packet_len)
donatien 0:8e01dca41002 364 {
donatien 0:8e01dca41002 365 chap_state *cstate = &chap[unit];
donatien 0:8e01dca41002 366 u_char *inp;
donatien 0:8e01dca41002 367 u_char code, id;
donatien 0:8e01dca41002 368 int len;
donatien 0:8e01dca41002 369
donatien 0:8e01dca41002 370 /*
donatien 0:8e01dca41002 371 * Parse header (code, id and length).
donatien 0:8e01dca41002 372 * If packet too short, drop it.
donatien 0:8e01dca41002 373 */
donatien 0:8e01dca41002 374 inp = inpacket;
donatien 0:8e01dca41002 375 if (packet_len < CHAP_HEADERLEN) {
donatien 0:8e01dca41002 376 CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n"));
donatien 0:8e01dca41002 377 return;
donatien 0:8e01dca41002 378 }
donatien 0:8e01dca41002 379 GETCHAR(code, inp);
donatien 0:8e01dca41002 380 GETCHAR(id, inp);
donatien 0:8e01dca41002 381 GETSHORT(len, inp);
donatien 0:8e01dca41002 382 if (len < CHAP_HEADERLEN) {
donatien 0:8e01dca41002 383 CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n"));
donatien 0:8e01dca41002 384 return;
donatien 0:8e01dca41002 385 }
donatien 0:8e01dca41002 386 if (len > packet_len) {
donatien 0:8e01dca41002 387 CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n"));
donatien 0:8e01dca41002 388 return;
donatien 0:8e01dca41002 389 }
donatien 0:8e01dca41002 390 len -= CHAP_HEADERLEN;
donatien 0:8e01dca41002 391
donatien 0:8e01dca41002 392 /*
donatien 0:8e01dca41002 393 * Action depends on code (as in fact it usually does :-).
donatien 0:8e01dca41002 394 */
donatien 0:8e01dca41002 395 switch (code) {
donatien 0:8e01dca41002 396 case CHAP_CHALLENGE:
donatien 0:8e01dca41002 397 ChapReceiveChallenge(cstate, inp, id, len);
donatien 0:8e01dca41002 398 break;
donatien 0:8e01dca41002 399
donatien 0:8e01dca41002 400 case CHAP_RESPONSE:
donatien 0:8e01dca41002 401 ChapReceiveResponse(cstate, inp, id, len);
donatien 0:8e01dca41002 402 break;
donatien 0:8e01dca41002 403
donatien 0:8e01dca41002 404 case CHAP_FAILURE:
donatien 0:8e01dca41002 405 ChapReceiveFailure(cstate, inp, id, len);
donatien 0:8e01dca41002 406 break;
donatien 0:8e01dca41002 407
donatien 0:8e01dca41002 408 case CHAP_SUCCESS:
donatien 0:8e01dca41002 409 ChapReceiveSuccess(cstate, inp, id, len);
donatien 0:8e01dca41002 410 break;
donatien 0:8e01dca41002 411
donatien 0:8e01dca41002 412 default: /* Need code reject? */
donatien 0:8e01dca41002 413 CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code));
donatien 0:8e01dca41002 414 break;
donatien 0:8e01dca41002 415 }
donatien 0:8e01dca41002 416 }
donatien 0:8e01dca41002 417
donatien 0:8e01dca41002 418
donatien 0:8e01dca41002 419 /*
donatien 0:8e01dca41002 420 * ChapReceiveChallenge - Receive Challenge and send Response.
donatien 0:8e01dca41002 421 */
donatien 0:8e01dca41002 422 static void
donatien 0:8e01dca41002 423 ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len)
donatien 0:8e01dca41002 424 {
donatien 0:8e01dca41002 425 int rchallenge_len;
donatien 0:8e01dca41002 426 u_char *rchallenge;
donatien 0:8e01dca41002 427 int secret_len;
donatien 0:8e01dca41002 428 char secret[MAXSECRETLEN];
donatien 0:8e01dca41002 429 char rhostname[256];
donatien 0:8e01dca41002 430 MD5_CTX mdContext;
donatien 0:8e01dca41002 431 u_char hash[MD5_SIGNATURE_SIZE];
donatien 0:8e01dca41002 432
donatien 0:8e01dca41002 433 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id));
donatien 0:8e01dca41002 434 if (cstate->clientstate == CHAPCS_CLOSED ||
donatien 0:8e01dca41002 435 cstate->clientstate == CHAPCS_PENDING) {
donatien 0:8e01dca41002 436 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n",
donatien 0:8e01dca41002 437 cstate->clientstate));
donatien 0:8e01dca41002 438 return;
donatien 0:8e01dca41002 439 }
donatien 0:8e01dca41002 440
donatien 0:8e01dca41002 441 if (len < 2) {
donatien 0:8e01dca41002 442 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
donatien 0:8e01dca41002 443 return;
donatien 0:8e01dca41002 444 }
donatien 0:8e01dca41002 445
donatien 0:8e01dca41002 446 GETCHAR(rchallenge_len, inp);
donatien 0:8e01dca41002 447 len -= sizeof (u_char) + rchallenge_len; /* now name field length */
donatien 0:8e01dca41002 448 if (len < 0) {
donatien 0:8e01dca41002 449 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
donatien 0:8e01dca41002 450 return;
donatien 0:8e01dca41002 451 }
donatien 0:8e01dca41002 452 rchallenge = inp;
donatien 0:8e01dca41002 453 INCPTR(rchallenge_len, inp);
donatien 0:8e01dca41002 454
donatien 0:8e01dca41002 455 if (len >= (int)sizeof(rhostname)) {
donatien 0:8e01dca41002 456 len = sizeof(rhostname) - 1;
donatien 0:8e01dca41002 457 }
donatien 0:8e01dca41002 458 BCOPY(inp, rhostname, len);
donatien 0:8e01dca41002 459 rhostname[len] = '\000';
donatien 0:8e01dca41002 460
donatien 0:8e01dca41002 461 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n",
donatien 0:8e01dca41002 462 rhostname));
donatien 0:8e01dca41002 463
donatien 0:8e01dca41002 464 /* Microsoft doesn't send their name back in the PPP packet */
donatien 0:8e01dca41002 465 if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) {
donatien 0:8e01dca41002 466 strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname));
donatien 0:8e01dca41002 467 rhostname[sizeof(rhostname) - 1] = 0;
donatien 0:8e01dca41002 468 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n",
donatien 0:8e01dca41002 469 rhostname));
donatien 0:8e01dca41002 470 }
donatien 0:8e01dca41002 471
donatien 0:8e01dca41002 472 /* get secret for authenticating ourselves with the specified host */
donatien 0:8e01dca41002 473 if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
donatien 0:8e01dca41002 474 secret, &secret_len, 0)) {
donatien 0:8e01dca41002 475 secret_len = 0; /* assume null secret if can't find one */
donatien 0:8e01dca41002 476 CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n",
donatien 0:8e01dca41002 477 rhostname));
donatien 0:8e01dca41002 478 }
donatien 0:8e01dca41002 479
donatien 0:8e01dca41002 480 /* cancel response send timeout if necessary */
donatien 0:8e01dca41002 481 if (cstate->clientstate == CHAPCS_RESPONSE) {
donatien 0:8e01dca41002 482 UNTIMEOUT(ChapResponseTimeout, cstate);
donatien 0:8e01dca41002 483 }
donatien 0:8e01dca41002 484
donatien 0:8e01dca41002 485 cstate->resp_id = id;
donatien 0:8e01dca41002 486 cstate->resp_transmits = 0;
donatien 0:8e01dca41002 487
donatien 0:8e01dca41002 488 /* generate MD based on negotiated type */
donatien 0:8e01dca41002 489 switch (cstate->resp_type) {
donatien 0:8e01dca41002 490
donatien 0:8e01dca41002 491 case CHAP_DIGEST_MD5:
donatien 0:8e01dca41002 492 MD5Init(&mdContext);
donatien 0:8e01dca41002 493 MD5Update(&mdContext, &cstate->resp_id, 1);
donatien 0:8e01dca41002 494 MD5Update(&mdContext, (u_char*)secret, secret_len);
donatien 0:8e01dca41002 495 MD5Update(&mdContext, rchallenge, rchallenge_len);
donatien 0:8e01dca41002 496 MD5Final(hash, &mdContext);
donatien 0:8e01dca41002 497 BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
donatien 0:8e01dca41002 498 cstate->resp_length = MD5_SIGNATURE_SIZE;
donatien 0:8e01dca41002 499 break;
donatien 0:8e01dca41002 500
donatien 0:8e01dca41002 501 #if MSCHAP_SUPPORT
donatien 0:8e01dca41002 502 case CHAP_MICROSOFT:
donatien 0:8e01dca41002 503 ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
donatien 0:8e01dca41002 504 break;
donatien 0:8e01dca41002 505 #endif
donatien 0:8e01dca41002 506
donatien 0:8e01dca41002 507 default:
donatien 0:8e01dca41002 508 CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type));
donatien 0:8e01dca41002 509 return;
donatien 0:8e01dca41002 510 }
donatien 0:8e01dca41002 511
donatien 0:8e01dca41002 512 BZERO(secret, sizeof(secret));
donatien 0:8e01dca41002 513 ChapSendResponse(cstate);
donatien 0:8e01dca41002 514 }
donatien 0:8e01dca41002 515
donatien 0:8e01dca41002 516
donatien 0:8e01dca41002 517 /*
donatien 0:8e01dca41002 518 * ChapReceiveResponse - Receive and process response.
donatien 0:8e01dca41002 519 */
donatien 0:8e01dca41002 520 static void
donatien 0:8e01dca41002 521 ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
donatien 0:8e01dca41002 522 {
donatien 0:8e01dca41002 523 u_char *remmd, remmd_len;
donatien 0:8e01dca41002 524 int secret_len, old_state;
donatien 0:8e01dca41002 525 int code;
donatien 0:8e01dca41002 526 char rhostname[256];
donatien 0:8e01dca41002 527 MD5_CTX mdContext;
donatien 0:8e01dca41002 528 char secret[MAXSECRETLEN];
donatien 0:8e01dca41002 529 u_char hash[MD5_SIGNATURE_SIZE];
donatien 0:8e01dca41002 530
donatien 0:8e01dca41002 531 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id));
donatien 0:8e01dca41002 532
donatien 0:8e01dca41002 533 if (cstate->serverstate == CHAPSS_CLOSED ||
donatien 0:8e01dca41002 534 cstate->serverstate == CHAPSS_PENDING) {
donatien 0:8e01dca41002 535 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n",
donatien 0:8e01dca41002 536 cstate->serverstate));
donatien 0:8e01dca41002 537 return;
donatien 0:8e01dca41002 538 }
donatien 0:8e01dca41002 539
donatien 0:8e01dca41002 540 if (id != cstate->chal_id) {
donatien 0:8e01dca41002 541 return; /* doesn't match ID of last challenge */
donatien 0:8e01dca41002 542 }
donatien 0:8e01dca41002 543
donatien 0:8e01dca41002 544 /*
donatien 0:8e01dca41002 545 * If we have received a duplicate or bogus Response,
donatien 0:8e01dca41002 546 * we have to send the same answer (Success/Failure)
donatien 0:8e01dca41002 547 * as we did for the first Response we saw.
donatien 0:8e01dca41002 548 */
donatien 0:8e01dca41002 549 if (cstate->serverstate == CHAPSS_OPEN) {
donatien 0:8e01dca41002 550 ChapSendStatus(cstate, CHAP_SUCCESS);
donatien 0:8e01dca41002 551 return;
donatien 0:8e01dca41002 552 }
donatien 0:8e01dca41002 553 if (cstate->serverstate == CHAPSS_BADAUTH) {
donatien 0:8e01dca41002 554 ChapSendStatus(cstate, CHAP_FAILURE);
donatien 0:8e01dca41002 555 return;
donatien 0:8e01dca41002 556 }
donatien 0:8e01dca41002 557
donatien 0:8e01dca41002 558 if (len < 2) {
donatien 0:8e01dca41002 559 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
donatien 0:8e01dca41002 560 return;
donatien 0:8e01dca41002 561 }
donatien 0:8e01dca41002 562 GETCHAR(remmd_len, inp); /* get length of MD */
donatien 0:8e01dca41002 563 remmd = inp; /* get pointer to MD */
donatien 0:8e01dca41002 564 INCPTR(remmd_len, inp);
donatien 0:8e01dca41002 565
donatien 0:8e01dca41002 566 len -= sizeof (u_char) + remmd_len;
donatien 0:8e01dca41002 567 if (len < 0) {
donatien 0:8e01dca41002 568 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
donatien 0:8e01dca41002 569 return;
donatien 0:8e01dca41002 570 }
donatien 0:8e01dca41002 571
donatien 0:8e01dca41002 572 UNTIMEOUT(ChapChallengeTimeout, cstate);
donatien 0:8e01dca41002 573
donatien 0:8e01dca41002 574 if (len >= (int)sizeof(rhostname)) {
donatien 0:8e01dca41002 575 len = sizeof(rhostname) - 1;
donatien 0:8e01dca41002 576 }
donatien 0:8e01dca41002 577 BCOPY(inp, rhostname, len);
donatien 0:8e01dca41002 578 rhostname[len] = '\000';
donatien 0:8e01dca41002 579
donatien 0:8e01dca41002 580 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n",
donatien 0:8e01dca41002 581 rhostname));
donatien 0:8e01dca41002 582
donatien 0:8e01dca41002 583 /*
donatien 0:8e01dca41002 584 * Get secret for authenticating them with us,
donatien 0:8e01dca41002 585 * do the hash ourselves, and compare the result.
donatien 0:8e01dca41002 586 */
donatien 0:8e01dca41002 587 code = CHAP_FAILURE;
donatien 0:8e01dca41002 588 if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
donatien 0:8e01dca41002 589 secret, &secret_len, 1)) {
donatien 0:8e01dca41002 590 CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n",
donatien 0:8e01dca41002 591 rhostname));
donatien 0:8e01dca41002 592 } else {
donatien 0:8e01dca41002 593 /* generate MD based on negotiated type */
donatien 0:8e01dca41002 594 switch (cstate->chal_type) {
donatien 0:8e01dca41002 595
donatien 0:8e01dca41002 596 case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
donatien 0:8e01dca41002 597 if (remmd_len != MD5_SIGNATURE_SIZE) {
donatien 0:8e01dca41002 598 break; /* it's not even the right length */
donatien 0:8e01dca41002 599 }
donatien 0:8e01dca41002 600 MD5Init(&mdContext);
donatien 0:8e01dca41002 601 MD5Update(&mdContext, &cstate->chal_id, 1);
donatien 0:8e01dca41002 602 MD5Update(&mdContext, (u_char*)secret, secret_len);
donatien 0:8e01dca41002 603 MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
donatien 0:8e01dca41002 604 MD5Final(hash, &mdContext);
donatien 0:8e01dca41002 605
donatien 0:8e01dca41002 606 /* compare local and remote MDs and send the appropriate status */
donatien 0:8e01dca41002 607 if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) {
donatien 0:8e01dca41002 608 code = CHAP_SUCCESS; /* they are the same! */
donatien 0:8e01dca41002 609 }
donatien 0:8e01dca41002 610 break;
donatien 0:8e01dca41002 611
donatien 0:8e01dca41002 612 default:
donatien 0:8e01dca41002 613 CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type));
donatien 0:8e01dca41002 614 }
donatien 0:8e01dca41002 615 }
donatien 0:8e01dca41002 616
donatien 0:8e01dca41002 617 BZERO(secret, sizeof(secret));
donatien 0:8e01dca41002 618 ChapSendStatus(cstate, code);
donatien 0:8e01dca41002 619
donatien 0:8e01dca41002 620 if (code == CHAP_SUCCESS) {
donatien 0:8e01dca41002 621 old_state = cstate->serverstate;
donatien 0:8e01dca41002 622 cstate->serverstate = CHAPSS_OPEN;
donatien 0:8e01dca41002 623 if (old_state == CHAPSS_INITIAL_CHAL) {
donatien 0:8e01dca41002 624 auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
donatien 0:8e01dca41002 625 }
donatien 0:8e01dca41002 626 if (cstate->chal_interval != 0) {
donatien 0:8e01dca41002 627 TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
donatien 0:8e01dca41002 628 }
donatien 0:8e01dca41002 629 } else {
donatien 0:8e01dca41002 630 CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n"));
donatien 0:8e01dca41002 631 cstate->serverstate = CHAPSS_BADAUTH;
donatien 0:8e01dca41002 632 auth_peer_fail(cstate->unit, PPP_CHAP);
donatien 0:8e01dca41002 633 }
donatien 0:8e01dca41002 634 }
donatien 0:8e01dca41002 635
donatien 0:8e01dca41002 636 /*
donatien 0:8e01dca41002 637 * ChapReceiveSuccess - Receive Success
donatien 0:8e01dca41002 638 */
donatien 0:8e01dca41002 639 static void
donatien 0:8e01dca41002 640 ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len)
donatien 0:8e01dca41002 641 {
donatien 0:8e01dca41002 642 LWIP_UNUSED_ARG(id);
donatien 0:8e01dca41002 643 LWIP_UNUSED_ARG(inp);
donatien 0:8e01dca41002 644
donatien 0:8e01dca41002 645 CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id));
donatien 0:8e01dca41002 646
donatien 0:8e01dca41002 647 if (cstate->clientstate == CHAPCS_OPEN) {
donatien 0:8e01dca41002 648 /* presumably an answer to a duplicate response */
donatien 0:8e01dca41002 649 return;
donatien 0:8e01dca41002 650 }
donatien 0:8e01dca41002 651
donatien 0:8e01dca41002 652 if (cstate->clientstate != CHAPCS_RESPONSE) {
donatien 0:8e01dca41002 653 /* don't know what this is */
donatien 0:8e01dca41002 654 CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n",
donatien 0:8e01dca41002 655 cstate->clientstate));
donatien 0:8e01dca41002 656 return;
donatien 0:8e01dca41002 657 }
donatien 0:8e01dca41002 658
donatien 0:8e01dca41002 659 UNTIMEOUT(ChapResponseTimeout, cstate);
donatien 0:8e01dca41002 660
donatien 0:8e01dca41002 661 /*
donatien 0:8e01dca41002 662 * Print message.
donatien 0:8e01dca41002 663 */
donatien 0:8e01dca41002 664 if (len > 0) {
donatien 0:8e01dca41002 665 PRINTMSG(inp, len);
donatien 0:8e01dca41002 666 }
donatien 0:8e01dca41002 667
donatien 0:8e01dca41002 668 cstate->clientstate = CHAPCS_OPEN;
donatien 0:8e01dca41002 669
donatien 0:8e01dca41002 670 auth_withpeer_success(cstate->unit, PPP_CHAP);
donatien 0:8e01dca41002 671 }
donatien 0:8e01dca41002 672
donatien 0:8e01dca41002 673
donatien 0:8e01dca41002 674 /*
donatien 0:8e01dca41002 675 * ChapReceiveFailure - Receive failure.
donatien 0:8e01dca41002 676 */
donatien 0:8e01dca41002 677 static void
donatien 0:8e01dca41002 678 ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
donatien 0:8e01dca41002 679 {
donatien 0:8e01dca41002 680 LWIP_UNUSED_ARG(id);
donatien 0:8e01dca41002 681 LWIP_UNUSED_ARG(inp);
donatien 0:8e01dca41002 682
donatien 0:8e01dca41002 683 CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id));
donatien 0:8e01dca41002 684
donatien 0:8e01dca41002 685 if (cstate->clientstate != CHAPCS_RESPONSE) {
donatien 0:8e01dca41002 686 /* don't know what this is */
donatien 0:8e01dca41002 687 CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n",
donatien 0:8e01dca41002 688 cstate->clientstate));
donatien 0:8e01dca41002 689 return;
donatien 0:8e01dca41002 690 }
donatien 0:8e01dca41002 691
donatien 0:8e01dca41002 692 UNTIMEOUT(ChapResponseTimeout, cstate);
donatien 0:8e01dca41002 693
donatien 0:8e01dca41002 694 /*
donatien 0:8e01dca41002 695 * Print message.
donatien 0:8e01dca41002 696 */
donatien 0:8e01dca41002 697 if (len > 0) {
donatien 0:8e01dca41002 698 PRINTMSG(inp, len);
donatien 0:8e01dca41002 699 }
donatien 0:8e01dca41002 700
donatien 0:8e01dca41002 701 CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n"));
donatien 0:8e01dca41002 702 auth_withpeer_fail(cstate->unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
donatien 0:8e01dca41002 703 }
donatien 0:8e01dca41002 704
donatien 0:8e01dca41002 705
donatien 0:8e01dca41002 706 /*
donatien 0:8e01dca41002 707 * ChapSendChallenge - Send an Authenticate challenge.
donatien 0:8e01dca41002 708 */
donatien 0:8e01dca41002 709 static void
donatien 0:8e01dca41002 710 ChapSendChallenge(chap_state *cstate)
donatien 0:8e01dca41002 711 {
donatien 0:8e01dca41002 712 u_char *outp;
donatien 0:8e01dca41002 713 int chal_len, name_len;
donatien 0:8e01dca41002 714 int outlen;
donatien 0:8e01dca41002 715
donatien 0:8e01dca41002 716 chal_len = cstate->chal_len;
donatien 0:8e01dca41002 717 name_len = (int)strlen(cstate->chal_name);
donatien 0:8e01dca41002 718 outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
donatien 0:8e01dca41002 719 outp = outpacket_buf[cstate->unit];
donatien 0:8e01dca41002 720
donatien 0:8e01dca41002 721 MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
donatien 0:8e01dca41002 722
donatien 0:8e01dca41002 723 PUTCHAR(CHAP_CHALLENGE, outp);
donatien 0:8e01dca41002 724 PUTCHAR(cstate->chal_id, outp);
donatien 0:8e01dca41002 725 PUTSHORT(outlen, outp);
donatien 0:8e01dca41002 726
donatien 0:8e01dca41002 727 PUTCHAR(chal_len, outp); /* put length of challenge */
donatien 0:8e01dca41002 728 BCOPY(cstate->challenge, outp, chal_len);
donatien 0:8e01dca41002 729 INCPTR(chal_len, outp);
donatien 0:8e01dca41002 730
donatien 0:8e01dca41002 731 BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
donatien 0:8e01dca41002 732
donatien 0:8e01dca41002 733 pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
donatien 0:8e01dca41002 734
donatien 0:8e01dca41002 735 CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
donatien 0:8e01dca41002 736
donatien 0:8e01dca41002 737 TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
donatien 0:8e01dca41002 738 ++cstate->chal_transmits;
donatien 0:8e01dca41002 739 }
donatien 0:8e01dca41002 740
donatien 0:8e01dca41002 741
donatien 0:8e01dca41002 742 /*
donatien 0:8e01dca41002 743 * ChapSendStatus - Send a status response (ack or nak).
donatien 0:8e01dca41002 744 */
donatien 0:8e01dca41002 745 static void
donatien 0:8e01dca41002 746 ChapSendStatus(chap_state *cstate, int code)
donatien 0:8e01dca41002 747 {
donatien 0:8e01dca41002 748 u_char *outp;
donatien 0:8e01dca41002 749 int outlen, msglen;
donatien 0:8e01dca41002 750 char msg[256]; /* @todo: this can be a char*, no strcpy needed */
donatien 0:8e01dca41002 751
donatien 0:8e01dca41002 752 if (code == CHAP_SUCCESS) {
donatien 0:8e01dca41002 753 strcpy(msg, "Welcome!");
donatien 0:8e01dca41002 754 } else {
donatien 0:8e01dca41002 755 strcpy(msg, "I don't like you. Go 'way.");
donatien 0:8e01dca41002 756 }
donatien 0:8e01dca41002 757 msglen = (int)strlen(msg);
donatien 0:8e01dca41002 758
donatien 0:8e01dca41002 759 outlen = CHAP_HEADERLEN + msglen;
donatien 0:8e01dca41002 760 outp = outpacket_buf[cstate->unit];
donatien 0:8e01dca41002 761
donatien 0:8e01dca41002 762 MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
donatien 0:8e01dca41002 763
donatien 0:8e01dca41002 764 PUTCHAR(code, outp);
donatien 0:8e01dca41002 765 PUTCHAR(cstate->chal_id, outp);
donatien 0:8e01dca41002 766 PUTSHORT(outlen, outp);
donatien 0:8e01dca41002 767 BCOPY(msg, outp, msglen);
donatien 0:8e01dca41002 768 pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
donatien 0:8e01dca41002 769
donatien 0:8e01dca41002 770 CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code,
donatien 0:8e01dca41002 771 cstate->chal_id));
donatien 0:8e01dca41002 772 }
donatien 0:8e01dca41002 773
donatien 0:8e01dca41002 774 /*
donatien 0:8e01dca41002 775 * ChapGenChallenge is used to generate a pseudo-random challenge string of
donatien 0:8e01dca41002 776 * a pseudo-random length between min_len and max_len. The challenge
donatien 0:8e01dca41002 777 * string and its length are stored in *cstate, and various other fields of
donatien 0:8e01dca41002 778 * *cstate are initialized.
donatien 0:8e01dca41002 779 */
donatien 0:8e01dca41002 780
donatien 0:8e01dca41002 781 static void
donatien 0:8e01dca41002 782 ChapGenChallenge(chap_state *cstate)
donatien 0:8e01dca41002 783 {
donatien 0:8e01dca41002 784 int chal_len;
donatien 0:8e01dca41002 785 u_char *ptr = cstate->challenge;
donatien 0:8e01dca41002 786 int i;
donatien 0:8e01dca41002 787
donatien 0:8e01dca41002 788 /* pick a random challenge length between MIN_CHALLENGE_LENGTH and
donatien 0:8e01dca41002 789 MAX_CHALLENGE_LENGTH */
donatien 0:8e01dca41002 790 chal_len = (unsigned)
donatien 0:8e01dca41002 791 ((((magic() >> 16) *
donatien 0:8e01dca41002 792 (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16)
donatien 0:8e01dca41002 793 + MIN_CHALLENGE_LENGTH);
donatien 0:8e01dca41002 794 LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff);
donatien 0:8e01dca41002 795 cstate->chal_len = (u_char)chal_len;
donatien 0:8e01dca41002 796 cstate->chal_id = ++cstate->id;
donatien 0:8e01dca41002 797 cstate->chal_transmits = 0;
donatien 0:8e01dca41002 798
donatien 0:8e01dca41002 799 /* generate a random string */
donatien 0:8e01dca41002 800 for (i = 0; i < chal_len; i++ ) {
donatien 0:8e01dca41002 801 *ptr++ = (char) (magic() & 0xff);
donatien 0:8e01dca41002 802 }
donatien 0:8e01dca41002 803 }
donatien 0:8e01dca41002 804
donatien 0:8e01dca41002 805 /*
donatien 0:8e01dca41002 806 * ChapSendResponse - send a response packet with values as specified
donatien 0:8e01dca41002 807 * in *cstate.
donatien 0:8e01dca41002 808 */
donatien 0:8e01dca41002 809 /* ARGSUSED */
donatien 0:8e01dca41002 810 static void
donatien 0:8e01dca41002 811 ChapSendResponse(chap_state *cstate)
donatien 0:8e01dca41002 812 {
donatien 0:8e01dca41002 813 u_char *outp;
donatien 0:8e01dca41002 814 int outlen, md_len, name_len;
donatien 0:8e01dca41002 815
donatien 0:8e01dca41002 816 md_len = cstate->resp_length;
donatien 0:8e01dca41002 817 name_len = (int)strlen(cstate->resp_name);
donatien 0:8e01dca41002 818 outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
donatien 0:8e01dca41002 819 outp = outpacket_buf[cstate->unit];
donatien 0:8e01dca41002 820
donatien 0:8e01dca41002 821 MAKEHEADER(outp, PPP_CHAP);
donatien 0:8e01dca41002 822
donatien 0:8e01dca41002 823 PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
donatien 0:8e01dca41002 824 PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
donatien 0:8e01dca41002 825 PUTSHORT(outlen, outp); /* packet length */
donatien 0:8e01dca41002 826
donatien 0:8e01dca41002 827 PUTCHAR(md_len, outp); /* length of MD */
donatien 0:8e01dca41002 828 BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
donatien 0:8e01dca41002 829 INCPTR(md_len, outp);
donatien 0:8e01dca41002 830
donatien 0:8e01dca41002 831 BCOPY(cstate->resp_name, outp, name_len); /* append our name */
donatien 0:8e01dca41002 832
donatien 0:8e01dca41002 833 /* send the packet */
donatien 0:8e01dca41002 834 pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
donatien 0:8e01dca41002 835
donatien 0:8e01dca41002 836 cstate->clientstate = CHAPCS_RESPONSE;
donatien 0:8e01dca41002 837 TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
donatien 0:8e01dca41002 838 ++cstate->resp_transmits;
donatien 0:8e01dca41002 839 }
donatien 0:8e01dca41002 840
donatien 0:8e01dca41002 841 #if PPP_ADDITIONAL_CALLBACKS
donatien 0:8e01dca41002 842 static char *ChapCodenames[] = {
donatien 0:8e01dca41002 843 "Challenge", "Response", "Success", "Failure"
donatien 0:8e01dca41002 844 };
donatien 0:8e01dca41002 845 /*
donatien 0:8e01dca41002 846 * ChapPrintPkt - print the contents of a CHAP packet.
donatien 0:8e01dca41002 847 */
donatien 0:8e01dca41002 848 static int
donatien 0:8e01dca41002 849 ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
donatien 0:8e01dca41002 850 {
donatien 0:8e01dca41002 851 int code, id, len;
donatien 0:8e01dca41002 852 int clen, nlen;
donatien 0:8e01dca41002 853 u_char x;
donatien 0:8e01dca41002 854
donatien 0:8e01dca41002 855 if (plen < CHAP_HEADERLEN) {
donatien 0:8e01dca41002 856 return 0;
donatien 0:8e01dca41002 857 }
donatien 0:8e01dca41002 858 GETCHAR(code, p);
donatien 0:8e01dca41002 859 GETCHAR(id, p);
donatien 0:8e01dca41002 860 GETSHORT(len, p);
donatien 0:8e01dca41002 861 if (len < CHAP_HEADERLEN || len > plen) {
donatien 0:8e01dca41002 862 return 0;
donatien 0:8e01dca41002 863 }
donatien 0:8e01dca41002 864
donatien 0:8e01dca41002 865 if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) {
donatien 0:8e01dca41002 866 printer(arg, " %s", ChapCodenames[code-1]);
donatien 0:8e01dca41002 867 } else {
donatien 0:8e01dca41002 868 printer(arg, " code=0x%x", code);
donatien 0:8e01dca41002 869 }
donatien 0:8e01dca41002 870 printer(arg, " id=0x%x", id);
donatien 0:8e01dca41002 871 len -= CHAP_HEADERLEN;
donatien 0:8e01dca41002 872 switch (code) {
donatien 0:8e01dca41002 873 case CHAP_CHALLENGE:
donatien 0:8e01dca41002 874 case CHAP_RESPONSE:
donatien 0:8e01dca41002 875 if (len < 1) {
donatien 0:8e01dca41002 876 break;
donatien 0:8e01dca41002 877 }
donatien 0:8e01dca41002 878 clen = p[0];
donatien 0:8e01dca41002 879 if (len < clen + 1) {
donatien 0:8e01dca41002 880 break;
donatien 0:8e01dca41002 881 }
donatien 0:8e01dca41002 882 ++p;
donatien 0:8e01dca41002 883 nlen = len - clen - 1;
donatien 0:8e01dca41002 884 printer(arg, " <");
donatien 0:8e01dca41002 885 for (; clen > 0; --clen) {
donatien 0:8e01dca41002 886 GETCHAR(x, p);
donatien 0:8e01dca41002 887 printer(arg, "%.2x", x);
donatien 0:8e01dca41002 888 }
donatien 0:8e01dca41002 889 printer(arg, ">, name = %.*Z", nlen, p);
donatien 0:8e01dca41002 890 break;
donatien 0:8e01dca41002 891 case CHAP_FAILURE:
donatien 0:8e01dca41002 892 case CHAP_SUCCESS:
donatien 0:8e01dca41002 893 printer(arg, " %.*Z", len, p);
donatien 0:8e01dca41002 894 break;
donatien 0:8e01dca41002 895 default:
donatien 0:8e01dca41002 896 for (clen = len; clen > 0; --clen) {
donatien 0:8e01dca41002 897 GETCHAR(x, p);
donatien 0:8e01dca41002 898 printer(arg, " %.2x", x);
donatien 0:8e01dca41002 899 }
donatien 0:8e01dca41002 900 }
donatien 0:8e01dca41002 901
donatien 0:8e01dca41002 902 return len + CHAP_HEADERLEN;
donatien 0:8e01dca41002 903 }
donatien 0:8e01dca41002 904 #endif /* PPP_ADDITIONAL_CALLBACKS */
donatien 0:8e01dca41002 905
donatien 0:8e01dca41002 906 #endif /* CHAP_SUPPORT */
donatien 0:8e01dca41002 907
donatien 0:8e01dca41002 908 #endif /* PPP_SUPPORT */