Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.

Dependencies:   mbed

Committer:
iva2k
Date:
Sat Jun 12 06:01:50 2010 +0000
Revision:
0:e614f7875b60

        

Who changed what in which revision?

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