]> git.sur5r.net Git - freertos/blob - Demo/Common/ethernet/lwIP/netif/ppp/pap.c
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@82 1d2547de-c912-0410-9cb9...
[freertos] / Demo / Common / ethernet / lwIP / netif / ppp / pap.c
1 /*****************************************************************************\r
2 * pap.c - Network Password Authentication Protocol program file.\r
3 *\r
4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.\r
5 * portions Copyright (c) 1997 by Global Election Systems Inc.\r
6 *\r
7 * The authors hereby grant permission to use, copy, modify, distribute,\r
8 * and license this software and its documentation for any purpose, provided\r
9 * that existing copyright notices are retained in all copies and that this\r
10 * notice and the following disclaimer are included verbatim in any \r
11 * distributions. No written agreement, license, or royalty fee is required\r
12 * for any of the authorized uses.\r
13 *\r
14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR\r
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
24 *\r
25 ******************************************************************************\r
26 * REVISION HISTORY\r
27 *\r
28 * 03-01-01 Marc Boucher <marc@mbsi.ca>\r
29 *   Ported to lwIP.\r
30 * 97-12-12 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.\r
31 *       Original.\r
32 *****************************************************************************/\r
33 /*\r
34  * upap.c - User/Password Authentication Protocol.\r
35  *\r
36  * Copyright (c) 1989 Carnegie Mellon University.\r
37  * All rights reserved.\r
38  *\r
39  * Redistribution and use in source and binary forms are permitted\r
40  * provided that the above copyright notice and this paragraph are\r
41  * duplicated in all such forms and that any documentation,\r
42  * advertising materials, and other materials related to such\r
43  * distribution and use acknowledge that the software was developed\r
44  * by Carnegie Mellon University.  The name of the\r
45  * University may not be used to endorse or promote products derived\r
46  * from this software without specific prior written permission.\r
47  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR\r
48  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED\r
49  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.\r
50  */\r
51 \r
52 #include "ppp.h"\r
53 #include "auth.h"\r
54 #include "pap.h"\r
55 #include "pppdebug.h"\r
56 \r
57 \r
58 #if PAP_SUPPORT > 0\r
59 \r
60 /***********************************/\r
61 /*** LOCAL FUNCTION DECLARATIONS ***/\r
62 /***********************************/\r
63 /*\r
64  * Protocol entry points.\r
65  */\r
66 static void upap_init (int);\r
67 static void upap_lowerup (int);\r
68 static void upap_lowerdown (int);\r
69 static void upap_input (int, u_char *, int);\r
70 static void upap_protrej (int);\r
71 \r
72 static void upap_timeout (void *);\r
73 static void upap_reqtimeout (void *);\r
74 static void upap_rauthreq (upap_state *, u_char *, int, int);\r
75 static void upap_rauthack (upap_state *, u_char *, int, int);\r
76 static void upap_rauthnak (upap_state *, u_char *, int, int);\r
77 static void upap_sauthreq (upap_state *);\r
78 static void upap_sresp (upap_state *, u_char, u_char, char *, int);\r
79 \r
80 \r
81 \r
82 \r
83 /******************************/\r
84 /*** PUBLIC DATA STRUCTURES ***/\r
85 /******************************/\r
86 struct protent pap_protent = {\r
87     PPP_PAP,\r
88     upap_init,\r
89     upap_input,\r
90     upap_protrej,\r
91     upap_lowerup,\r
92     upap_lowerdown,\r
93     NULL,\r
94     NULL,\r
95 #if 0\r
96     upap_printpkt,\r
97     NULL,\r
98 #endif\r
99     1,\r
100     "PAP",\r
101 #if 0\r
102     NULL,\r
103     NULL,\r
104     NULL\r
105 #endif\r
106 };\r
107 \r
108 upap_state upap[NUM_PPP];               /* UPAP state; one for each unit */\r
109 \r
110 \r
111 \r
112 /***********************************/\r
113 /*** PUBLIC FUNCTION DEFINITIONS ***/\r
114 /***********************************/\r
115 /*\r
116  *  Set the default login name and password for the pap sessions\r
117  */\r
118 void upap_setloginpasswd(int unit, const char *luser, const char *lpassword)\r
119 {\r
120         upap_state *u = &upap[unit];\r
121         \r
122         /* Save the username and password we're given */\r
123         u->us_user = luser;\r
124         u->us_userlen = strlen(luser);\r
125         u->us_passwd = lpassword;\r
126         u->us_passwdlen = strlen(lpassword);\r
127 }\r
128 \r
129 \r
130 /*\r
131  * upap_authwithpeer - Authenticate us with our peer (start client).\r
132  *\r
133  * Set new state and send authenticate's.\r
134  */\r
135 void upap_authwithpeer(int unit, char *user, char *password)\r
136 {\r
137         upap_state *u = &upap[unit];\r
138         \r
139         UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%d\n",\r
140                                 unit, user, password, u->us_clientstate));\r
141         \r
142         upap_setloginpasswd(unit, user, password);\r
143 \r
144         u->us_transmits = 0;\r
145         \r
146         /* Lower layer up yet? */\r
147         if (u->us_clientstate == UPAPCS_INITIAL ||\r
148                         u->us_clientstate == UPAPCS_PENDING) {\r
149                 u->us_clientstate = UPAPCS_PENDING;\r
150                 return;\r
151         }\r
152         \r
153         upap_sauthreq(u);                       /* Start protocol */\r
154 }\r
155 \r
156 \r
157 /*\r
158  * upap_authpeer - Authenticate our peer (start server).\r
159  *\r
160  * Set new state.\r
161  */\r
162 void upap_authpeer(int unit)\r
163 {\r
164         upap_state *u = &upap[unit];\r
165         \r
166         /* Lower layer up yet? */\r
167         if (u->us_serverstate == UPAPSS_INITIAL ||\r
168                         u->us_serverstate == UPAPSS_PENDING) {\r
169                 u->us_serverstate = UPAPSS_PENDING;\r
170                 return;\r
171         }\r
172         \r
173         u->us_serverstate = UPAPSS_LISTEN;\r
174         if (u->us_reqtimeout > 0)\r
175                 TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);\r
176 }\r
177 \r
178 \r
179 \r
180 /**********************************/\r
181 /*** LOCAL FUNCTION DEFINITIONS ***/\r
182 /**********************************/\r
183 /*\r
184  * upap_init - Initialize a UPAP unit.\r
185  */\r
186 static void upap_init(int unit)\r
187 {\r
188         upap_state *u = &upap[unit];\r
189 \r
190         UPAPDEBUG((LOG_INFO, "upap_init: %d\n", unit)); \r
191         u->us_unit = unit;\r
192         u->us_user = NULL;\r
193         u->us_userlen = 0;\r
194         u->us_passwd = NULL;\r
195         u->us_passwdlen = 0;\r
196         u->us_clientstate = UPAPCS_INITIAL;\r
197         u->us_serverstate = UPAPSS_INITIAL;\r
198         u->us_id = 0;\r
199         u->us_timeouttime = UPAP_DEFTIMEOUT;\r
200         u->us_maxtransmits = 10;\r
201         u->us_reqtimeout = UPAP_DEFREQTIME;\r
202 }\r
203 \r
204 /*\r
205  * upap_timeout - Retransmission timer for sending auth-reqs expired.\r
206  */\r
207 static void upap_timeout(void *arg)\r
208 {\r
209         upap_state *u = (upap_state *) arg;\r
210         \r
211         UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%d\n", \r
212                                 u->us_unit, u->us_timeouttime, u->us_clientstate));\r
213         \r
214         if (u->us_clientstate != UPAPCS_AUTHREQ)\r
215                 return;\r
216         \r
217         if (u->us_transmits >= u->us_maxtransmits) {\r
218                 /* give up in disgust */\r
219                 UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requests\n"));\r
220                 u->us_clientstate = UPAPCS_BADAUTH;\r
221                 auth_withpeer_fail(u->us_unit, PPP_PAP);\r
222                 return;\r
223         }\r
224         \r
225         upap_sauthreq(u);               /* Send Authenticate-Request */\r
226 }\r
227 \r
228 \r
229 /*\r
230  * upap_reqtimeout - Give up waiting for the peer to send an auth-req.\r
231  */\r
232 static void upap_reqtimeout(void *arg)\r
233 {\r
234         upap_state *u = (upap_state *) arg;\r
235         \r
236         if (u->us_serverstate != UPAPSS_LISTEN)\r
237                 return;                 /* huh?? */\r
238         \r
239         auth_peer_fail(u->us_unit, PPP_PAP);\r
240         u->us_serverstate = UPAPSS_BADAUTH;\r
241 }\r
242 \r
243 \r
244 /*\r
245  * upap_lowerup - The lower layer is up.\r
246  *\r
247  * Start authenticating if pending.\r
248  */\r
249 static void upap_lowerup(int unit)\r
250 {\r
251         upap_state *u = &upap[unit];\r
252         \r
253         UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%d\n", unit, u->us_clientstate));\r
254         \r
255         if (u->us_clientstate == UPAPCS_INITIAL)\r
256                 u->us_clientstate = UPAPCS_CLOSED;\r
257         else if (u->us_clientstate == UPAPCS_PENDING) {\r
258                 upap_sauthreq(u);       /* send an auth-request */\r
259         }\r
260         \r
261         if (u->us_serverstate == UPAPSS_INITIAL)\r
262                 u->us_serverstate = UPAPSS_CLOSED;\r
263         else if (u->us_serverstate == UPAPSS_PENDING) {\r
264                 u->us_serverstate = UPAPSS_LISTEN;\r
265                 if (u->us_reqtimeout > 0)\r
266                         TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);\r
267         }\r
268 }\r
269 \r
270 \r
271 /*\r
272  * upap_lowerdown - The lower layer is down.\r
273  *\r
274  * Cancel all timeouts.\r
275  */\r
276 static void upap_lowerdown(int unit)\r
277 {\r
278         upap_state *u = &upap[unit];\r
279         \r
280         UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%d\n", unit, u->us_clientstate));\r
281         \r
282         if (u->us_clientstate == UPAPCS_AUTHREQ)        /* Timeout pending? */\r
283                 UNTIMEOUT(upap_timeout, u);             /* Cancel timeout */\r
284         if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)\r
285                 UNTIMEOUT(upap_reqtimeout, u);\r
286         \r
287         u->us_clientstate = UPAPCS_INITIAL;\r
288         u->us_serverstate = UPAPSS_INITIAL;\r
289 }\r
290 \r
291 \r
292 /*\r
293  * upap_protrej - Peer doesn't speak this protocol.\r
294  *\r
295  * This shouldn't happen.  In any case, pretend lower layer went down.\r
296  */\r
297 static void upap_protrej(int unit)\r
298 {\r
299         upap_state *u = &upap[unit];\r
300         \r
301         if (u->us_clientstate == UPAPCS_AUTHREQ) {\r
302                 UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-reject\n"));\r
303                 auth_withpeer_fail(unit, PPP_PAP);\r
304         }\r
305         if (u->us_serverstate == UPAPSS_LISTEN) {\r
306                 UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n"));\r
307                 auth_peer_fail(unit, PPP_PAP);\r
308         }\r
309         upap_lowerdown(unit);\r
310 }\r
311 \r
312 \r
313 /*\r
314  * upap_input - Input UPAP packet.\r
315  */\r
316 static void upap_input(int unit, u_char *inpacket, int l)\r
317 {\r
318         upap_state *u = &upap[unit];\r
319         u_char *inp;\r
320         u_char code, id;\r
321         int len;\r
322         \r
323         /*\r
324          * Parse header (code, id and length).\r
325          * If packet too short, drop it.\r
326          */\r
327         inp = inpacket;\r
328         if (l < UPAP_HEADERLEN) {\r
329                 UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.\n"));\r
330                 return;\r
331         }\r
332         GETCHAR(code, inp);\r
333         GETCHAR(id, inp);\r
334         GETSHORT(len, inp);\r
335         if (len < UPAP_HEADERLEN) {\r
336                 UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n"));\r
337                 return;\r
338         }\r
339         if (len > l) {\r
340                 UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n"));\r
341                 return;\r
342         }\r
343         len -= UPAP_HEADERLEN;\r
344         \r
345         /*\r
346          * Action depends on code.\r
347          */\r
348         switch (code) {\r
349         case UPAP_AUTHREQ:\r
350                 upap_rauthreq(u, inp, id, len);\r
351                 break;\r
352         \r
353         case UPAP_AUTHACK:\r
354                 upap_rauthack(u, inp, id, len);\r
355                 break;\r
356         \r
357         case UPAP_AUTHNAK:\r
358                 upap_rauthnak(u, inp, id, len);\r
359                 break;\r
360         \r
361         default:                                /* XXX Need code reject */\r
362                 break;\r
363         }\r
364 }\r
365 \r
366 \r
367 /*\r
368  * upap_rauth - Receive Authenticate.\r
369  */\r
370 static void upap_rauthreq(\r
371         upap_state *u, \r
372         u_char *inp, \r
373         int id,\r
374         int len\r
375 )\r
376 {\r
377         u_char ruserlen, rpasswdlen;\r
378         char *ruser, *rpasswd;\r
379         int retcode;\r
380         char *msg;\r
381         int msglen;\r
382         \r
383         UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id));\r
384         \r
385         if (u->us_serverstate < UPAPSS_LISTEN)\r
386                 return;\r
387         \r
388         /*\r
389          * If we receive a duplicate authenticate-request, we are\r
390          * supposed to return the same status as for the first request.\r
391          */\r
392         if (u->us_serverstate == UPAPSS_OPEN) {\r
393                 upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */\r
394                 return;\r
395         }\r
396         if (u->us_serverstate == UPAPSS_BADAUTH) {\r
397                 upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */\r
398                 return;\r
399         }\r
400         \r
401         /*\r
402          * Parse user/passwd.\r
403          */\r
404         if (len < sizeof (u_char)) {\r
405                 UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));\r
406                 return;\r
407         }\r
408         GETCHAR(ruserlen, inp);\r
409         len -= sizeof (u_char) + ruserlen + sizeof (u_char);\r
410         if (len < 0) {\r
411                 UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));\r
412                 return;\r
413         }\r
414         ruser = (char *) inp;\r
415         INCPTR(ruserlen, inp);\r
416         GETCHAR(rpasswdlen, inp);\r
417         if (len < rpasswdlen) {\r
418                 UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));\r
419                 return;\r
420         }\r
421         rpasswd = (char *) inp;\r
422         \r
423         /*\r
424          * Check the username and password given.\r
425          */\r
426         retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,\r
427                            rpasswdlen, &msg, &msglen);\r
428         BZERO(rpasswd, rpasswdlen);\r
429         \r
430         upap_sresp(u, retcode, id, msg, msglen);\r
431         \r
432         if (retcode == UPAP_AUTHACK) {\r
433                 u->us_serverstate = UPAPSS_OPEN;\r
434                 auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);\r
435         } else {\r
436                 u->us_serverstate = UPAPSS_BADAUTH;\r
437                 auth_peer_fail(u->us_unit, PPP_PAP);\r
438         }\r
439         \r
440         if (u->us_reqtimeout > 0)\r
441                 UNTIMEOUT(upap_reqtimeout, u);\r
442 }\r
443 \r
444 \r
445 /*\r
446  * upap_rauthack - Receive Authenticate-Ack.\r
447  */\r
448 static void upap_rauthack(\r
449         upap_state *u,\r
450         u_char *inp,\r
451         int id,\r
452         int len\r
453 )\r
454 {\r
455         u_char msglen;\r
456         char *msg;\r
457         \r
458         UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate));\r
459         \r
460         if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */\r
461                 return;\r
462         \r
463         /*\r
464          * Parse message.\r
465          */\r
466         if (len < sizeof (u_char)) {\r
467                 UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));\r
468                 return;\r
469         }\r
470         GETCHAR(msglen, inp);\r
471         len -= sizeof (u_char);\r
472         if (len < msglen) {\r
473                 UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));\r
474                 return;\r
475         }\r
476         msg = (char *) inp;\r
477         PRINTMSG(msg, msglen);\r
478         \r
479         u->us_clientstate = UPAPCS_OPEN;\r
480         \r
481         auth_withpeer_success(u->us_unit, PPP_PAP);\r
482 }\r
483 \r
484 \r
485 /*\r
486  * upap_rauthnak - Receive Authenticate-Nakk.\r
487  */\r
488 static void upap_rauthnak(\r
489         upap_state *u,\r
490         u_char *inp,\r
491         int id,\r
492         int len\r
493 )\r
494 {\r
495         u_char msglen;\r
496         char *msg;\r
497         \r
498         UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));\r
499         \r
500         if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */\r
501                 return;\r
502         \r
503         /*\r
504          * Parse message.\r
505          */\r
506         if (len < sizeof (u_char)) {\r
507                 UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));\r
508                 return;\r
509         }\r
510         GETCHAR(msglen, inp);\r
511         len -= sizeof (u_char);\r
512         if (len < msglen) {\r
513                 UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));\r
514                 return;\r
515         }\r
516         msg = (char *) inp;\r
517         PRINTMSG(msg, msglen);\r
518         \r
519         u->us_clientstate = UPAPCS_BADAUTH;\r
520         \r
521         UPAPDEBUG((LOG_ERR, "PAP authentication failed\n"));\r
522         auth_withpeer_fail(u->us_unit, PPP_PAP);\r
523 }\r
524 \r
525 \r
526 /*\r
527  * upap_sauthreq - Send an Authenticate-Request.\r
528  */\r
529 static void upap_sauthreq(upap_state *u)\r
530 {\r
531         u_char *outp;\r
532         int outlen;\r
533         \r
534         outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) \r
535                         + u->us_userlen + u->us_passwdlen;\r
536         outp = outpacket_buf[u->us_unit];\r
537         \r
538         MAKEHEADER(outp, PPP_PAP);\r
539         \r
540         PUTCHAR(UPAP_AUTHREQ, outp);\r
541         PUTCHAR(++u->us_id, outp);\r
542         PUTSHORT(outlen, outp);\r
543         PUTCHAR(u->us_userlen, outp);\r
544         BCOPY(u->us_user, outp, u->us_userlen);\r
545         INCPTR(u->us_userlen, outp);\r
546         PUTCHAR(u->us_passwdlen, outp);\r
547         BCOPY(u->us_passwd, outp, u->us_passwdlen);\r
548         \r
549         pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);\r
550         \r
551         UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d\n", u->us_id));\r
552         \r
553         TIMEOUT(upap_timeout, u, u->us_timeouttime);\r
554         ++u->us_transmits;\r
555         u->us_clientstate = UPAPCS_AUTHREQ;\r
556 }\r
557 \r
558 \r
559 /*\r
560  * upap_sresp - Send a response (ack or nak).\r
561  */\r
562 static void upap_sresp(\r
563         upap_state *u,\r
564         u_char code, \r
565         u_char id,\r
566         char *msg,\r
567         int msglen\r
568 )\r
569 {\r
570         u_char *outp;\r
571         int outlen;\r
572         \r
573         outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;\r
574         outp = outpacket_buf[u->us_unit];\r
575         MAKEHEADER(outp, PPP_PAP);\r
576         \r
577         PUTCHAR(code, outp);\r
578         PUTCHAR(id, outp);\r
579         PUTSHORT(outlen, outp);\r
580         PUTCHAR(msglen, outp);\r
581         BCOPY(msg, outp, msglen);\r
582         pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);\r
583         \r
584         UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%d\n", \r
585                                 code, id, u->us_clientstate));\r
586 }\r
587 \r
588 #if 0\r
589 /*\r
590  * upap_printpkt - print the contents of a PAP packet.\r
591  */\r
592 static int upap_printpkt(\r
593         u_char *p,\r
594         int plen,\r
595         void (*printer) (void *, char *, ...),\r
596         void *arg\r
597 )\r
598 {\r
599         (void)p;\r
600         (void)plen;\r
601         (void)printer;\r
602         (void)arg;\r
603         return 0;\r
604 }\r
605 #endif\r
606 \r
607 #endif /* PAP_SUPPORT */\r
608 \r