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