Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merging for release RC2
[palacios-OLD.git] / geekos / src / lwip / 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 "lwip/opt.h"
53
54 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
55
56 #if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
57
58 #include "ppp.h"
59 #include "pppdebug.h"
60
61 #include "auth.h"
62 #include "pap.h"
63
64 /***********************************/
65 /*** LOCAL FUNCTION DECLARATIONS ***/
66 /***********************************/
67 /*
68  * Protocol entry points.
69  */
70 static void upap_init      (int);
71 static void upap_lowerup   (int);
72 static void upap_lowerdown (int);
73 static void upap_input     (int, u_char *, int);
74 static void upap_protrej   (int);
75
76 static void upap_timeout   (void *);
77 static void upap_reqtimeout(void *);
78 static void upap_rauthreq  (upap_state *, u_char *, int, int);
79 static void upap_rauthack  (upap_state *, u_char *, int, int);
80 static void upap_rauthnak  (upap_state *, u_char *, int, int);
81 static void upap_sauthreq  (upap_state *);
82 static void upap_sresp     (upap_state *, u_char, u_char, char *, int);
83
84
85 /******************************/
86 /*** PUBLIC DATA STRUCTURES ***/
87 /******************************/
88 struct protent pap_protent = {
89   PPP_PAP,
90   upap_init,
91   upap_input,
92   upap_protrej,
93   upap_lowerup,
94   upap_lowerdown,
95   NULL,
96   NULL,
97 #if 0
98   upap_printpkt,
99   NULL,
100 #endif
101   1,
102   "PAP",
103 #if 0
104   NULL,
105   NULL,
106   NULL
107 #endif
108 };
109
110 upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
111
112
113
114 /***********************************/
115 /*** PUBLIC FUNCTION DEFINITIONS ***/
116 /***********************************/
117 /*
118  *  Set the default login name and password for the pap sessions
119  */
120 void
121 upap_setloginpasswd(int unit, const char *luser, const char *lpassword)
122 {
123   upap_state *u = &upap[unit];
124   
125   /* Save the username and password we're given */
126   u->us_user = luser;
127   u->us_userlen = strlen(luser);
128   u->us_passwd = lpassword;
129   u->us_passwdlen = strlen(lpassword);
130 }
131
132
133 /*
134  * upap_authwithpeer - Authenticate us with our peer (start client).
135  *
136  * Set new state and send authenticate's.
137  */
138 void
139 upap_authwithpeer(int unit, char *user, char *password)
140 {
141   upap_state *u = &upap[unit];
142
143   UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%d\n",
144              unit, user, password, u->us_clientstate));
145
146   upap_setloginpasswd(unit, user, password);
147
148   u->us_transmits = 0;
149
150   /* Lower layer up yet? */
151   if (u->us_clientstate == UPAPCS_INITIAL ||
152       u->us_clientstate == UPAPCS_PENDING) {
153     u->us_clientstate = UPAPCS_PENDING;
154     return;
155   }
156
157   upap_sauthreq(u);      /* Start protocol */
158 }
159
160
161 /*
162  * upap_authpeer - Authenticate our peer (start server).
163  *
164  * Set new state.
165  */
166 void
167 upap_authpeer(int unit)
168 {
169   upap_state *u = &upap[unit];
170
171   /* Lower layer up yet? */
172   if (u->us_serverstate == UPAPSS_INITIAL ||
173       u->us_serverstate == UPAPSS_PENDING) {
174     u->us_serverstate = UPAPSS_PENDING;
175     return;
176   }
177
178   u->us_serverstate = UPAPSS_LISTEN;
179   if (u->us_reqtimeout > 0) {
180     TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
181   }
182 }
183
184
185
186 /**********************************/
187 /*** LOCAL FUNCTION DEFINITIONS ***/
188 /**********************************/
189 /*
190  * upap_init - Initialize a UPAP unit.
191  */
192 static void
193 upap_init(int unit)
194 {
195   upap_state *u = &upap[unit];
196
197   UPAPDEBUG((LOG_INFO, "upap_init: %d\n", unit));
198   u->us_unit         = unit;
199   u->us_user         = NULL;
200   u->us_userlen      = 0;
201   u->us_passwd       = NULL;
202   u->us_passwdlen    = 0;
203   u->us_clientstate  = UPAPCS_INITIAL;
204   u->us_serverstate  = UPAPSS_INITIAL;
205   u->us_id           = 0;
206   u->us_timeouttime  = UPAP_DEFTIMEOUT;
207   u->us_maxtransmits = 10;
208   u->us_reqtimeout   = UPAP_DEFREQTIME;
209 }
210
211 /*
212  * upap_timeout - Retransmission timer for sending auth-reqs expired.
213  */
214 static void
215 upap_timeout(void *arg)
216 {
217   upap_state *u = (upap_state *) arg;
218
219   UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%d\n", 
220         u->us_unit, u->us_timeouttime, u->us_clientstate));
221
222   if (u->us_clientstate != UPAPCS_AUTHREQ) {
223     return;
224   }
225
226   if (u->us_transmits >= u->us_maxtransmits) {
227     /* give up in disgust */
228     UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requests\n"));
229     u->us_clientstate = UPAPCS_BADAUTH;
230     auth_withpeer_fail(u->us_unit, PPP_PAP);
231     return;
232   }
233
234   upap_sauthreq(u);    /* Send Authenticate-Request */
235 }
236
237
238 /*
239  * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
240  */
241 static void
242 upap_reqtimeout(void *arg)
243 {
244   upap_state *u = (upap_state *) arg;
245
246   if (u->us_serverstate != UPAPSS_LISTEN) {
247     return; /* huh?? */
248   }
249
250   auth_peer_fail(u->us_unit, PPP_PAP);
251   u->us_serverstate = UPAPSS_BADAUTH;
252 }
253
254
255 /*
256  * upap_lowerup - The lower layer is up.
257  *
258  * Start authenticating if pending.
259  */
260 static void
261 upap_lowerup(int unit)
262 {
263   upap_state *u = &upap[unit];
264
265   UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%d\n", unit, u->us_clientstate));
266
267   if (u->us_clientstate == UPAPCS_INITIAL) {
268     u->us_clientstate = UPAPCS_CLOSED;
269   } else if (u->us_clientstate == UPAPCS_PENDING) {
270     upap_sauthreq(u);  /* send an auth-request */
271   }
272
273   if (u->us_serverstate == UPAPSS_INITIAL) {
274     u->us_serverstate = UPAPSS_CLOSED;
275   } else if (u->us_serverstate == UPAPSS_PENDING) {
276     u->us_serverstate = UPAPSS_LISTEN;
277     if (u->us_reqtimeout > 0) {
278       TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
279     }
280   }
281 }
282
283
284 /*
285  * upap_lowerdown - The lower layer is down.
286  *
287  * Cancel all timeouts.
288  */
289 static void
290 upap_lowerdown(int unit)
291 {
292   upap_state *u = &upap[unit];
293
294   UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%d\n", unit, u->us_clientstate));
295
296   if (u->us_clientstate == UPAPCS_AUTHREQ) { /* Timeout pending? */
297     UNTIMEOUT(upap_timeout, u);    /* Cancel timeout */
298   }
299   if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) {
300     UNTIMEOUT(upap_reqtimeout, u);
301   }
302
303   u->us_clientstate = UPAPCS_INITIAL;
304   u->us_serverstate = UPAPSS_INITIAL;
305 }
306
307
308 /*
309  * upap_protrej - Peer doesn't speak this protocol.
310  *
311  * This shouldn't happen.  In any case, pretend lower layer went down.
312  */
313 static void
314 upap_protrej(int unit)
315 {
316   upap_state *u = &upap[unit];
317
318   if (u->us_clientstate == UPAPCS_AUTHREQ) {
319     UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-reject\n"));
320     auth_withpeer_fail(unit, PPP_PAP);
321   }
322   if (u->us_serverstate == UPAPSS_LISTEN) {
323     UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n"));
324     auth_peer_fail(unit, PPP_PAP);
325   }
326   upap_lowerdown(unit);
327 }
328
329
330 /*
331  * upap_input - Input UPAP packet.
332  */
333 static void
334 upap_input(int unit, u_char *inpacket, int l)
335 {
336   upap_state *u = &upap[unit];
337   u_char *inp;
338   u_char code, id;
339   int len;
340
341   /*
342    * Parse header (code, id and length).
343    * If packet too short, drop it.
344    */
345   inp = inpacket;
346   if (l < UPAP_HEADERLEN) {
347     UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.\n"));
348     return;
349   }
350   GETCHAR(code, inp);
351   GETCHAR(id, inp);
352   GETSHORT(len, inp);
353   if (len < UPAP_HEADERLEN) {
354     UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n"));
355     return;
356   }
357   if (len > l) {
358     UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n"));
359     return;
360   }
361   len -= UPAP_HEADERLEN;
362
363   /*
364    * Action depends on code.
365    */
366   switch (code) {
367     case UPAP_AUTHREQ:
368       upap_rauthreq(u, inp, id, len);
369       break;
370
371     case UPAP_AUTHACK:
372       upap_rauthack(u, inp, id, len);
373       break;
374
375     case UPAP_AUTHNAK:
376       upap_rauthnak(u, inp, id, len);
377       break;
378
379     default:        /* XXX Need code reject */
380       break;
381   }
382 }
383
384
385 /*
386  * upap_rauth - Receive Authenticate.
387  */
388 static void
389 upap_rauthreq(upap_state *u, u_char *inp, int id, int len)
390 {
391   u_char ruserlen, rpasswdlen;
392   char *ruser, *rpasswd;
393   int retcode;
394   char *msg;
395   int msglen;
396
397   UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id));
398
399   if (u->us_serverstate < UPAPSS_LISTEN) {
400     return;
401   }
402
403   /*
404    * If we receive a duplicate authenticate-request, we are
405    * supposed to return the same status as for the first request.
406    */
407   if (u->us_serverstate == UPAPSS_OPEN) {
408     upap_sresp(u, UPAP_AUTHACK, id, "", 0);  /* return auth-ack */
409     return;
410   }
411   if (u->us_serverstate == UPAPSS_BADAUTH) {
412     upap_sresp(u, UPAP_AUTHNAK, id, "", 0);  /* return auth-nak */
413     return;
414   }
415
416   /*
417    * Parse user/passwd.
418    */
419   if (len < sizeof (u_char)) {
420     UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
421     return;
422   }
423   GETCHAR(ruserlen, inp);
424   len -= sizeof (u_char) + ruserlen + sizeof (u_char);
425   if (len < 0) {
426     UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
427     return;
428   }
429   ruser = (char *) inp;
430   INCPTR(ruserlen, inp);
431   GETCHAR(rpasswdlen, inp);
432   if (len < rpasswdlen) {
433     UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
434     return;
435   }
436   rpasswd = (char *) inp;
437
438   /*
439    * Check the username and password given.
440    */
441   retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen);
442   BZERO(rpasswd, rpasswdlen);
443
444   upap_sresp(u, retcode, id, msg, msglen);
445
446   if (retcode == UPAP_AUTHACK) {
447     u->us_serverstate = UPAPSS_OPEN;
448     auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
449   } else {
450     u->us_serverstate = UPAPSS_BADAUTH;
451     auth_peer_fail(u->us_unit, PPP_PAP);
452   }
453
454   if (u->us_reqtimeout > 0) {
455     UNTIMEOUT(upap_reqtimeout, u);
456   }
457 }
458
459
460 /*
461  * upap_rauthack - Receive Authenticate-Ack.
462  */
463 static void
464 upap_rauthack(upap_state *u, u_char *inp, int id, int len)
465 {
466   u_char msglen;
467   char *msg;
468
469   LWIP_UNUSED_ARG(id);
470
471   UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate));
472
473   if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
474     return;
475   }
476
477   /*
478    * Parse message.
479    */
480   if (len < sizeof (u_char)) {
481     UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
482     return;
483   }
484   GETCHAR(msglen, inp);
485   len -= sizeof (u_char);
486   if (len < msglen) {
487     UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
488     return;
489   }
490   msg = (char *) inp;
491   PRINTMSG(msg, msglen);
492
493   u->us_clientstate = UPAPCS_OPEN;
494
495   auth_withpeer_success(u->us_unit, PPP_PAP);
496 }
497
498
499 /*
500  * upap_rauthnak - Receive Authenticate-Nakk.
501  */
502 static void
503 upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
504 {
505   u_char msglen;
506   char *msg;
507
508   LWIP_UNUSED_ARG(id);
509
510   UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));
511
512   if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
513     return;
514   }
515
516   /*
517    * Parse message.
518    */
519   if (len < sizeof (u_char)) {
520     UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
521     return;
522   }
523   GETCHAR(msglen, inp);
524   len -= sizeof (u_char);
525   if (len < msglen) {
526     UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
527     return;
528   }
529   msg = (char *) inp;
530   PRINTMSG(msg, msglen);
531
532   u->us_clientstate = UPAPCS_BADAUTH;
533
534   UPAPDEBUG((LOG_ERR, "PAP authentication failed\n"));
535   auth_withpeer_fail(u->us_unit, PPP_PAP);
536 }
537
538
539 /*
540  * upap_sauthreq - Send an Authenticate-Request.
541  */
542 static void
543 upap_sauthreq(upap_state *u)
544 {
545   u_char *outp;
546   int outlen;
547
548   outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) 
549          + u->us_userlen + u->us_passwdlen;
550   outp = outpacket_buf[u->us_unit];
551
552   MAKEHEADER(outp, PPP_PAP);
553
554   PUTCHAR(UPAP_AUTHREQ, outp);
555   PUTCHAR(++u->us_id, outp);
556   PUTSHORT(outlen, outp);
557   PUTCHAR(u->us_userlen, outp);
558   BCOPY(u->us_user, outp, u->us_userlen);
559   INCPTR(u->us_userlen, outp);
560   PUTCHAR(u->us_passwdlen, outp);
561   BCOPY(u->us_passwd, outp, u->us_passwdlen);
562
563   pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
564
565   UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d\n", u->us_id));
566
567   TIMEOUT(upap_timeout, u, u->us_timeouttime);
568   ++u->us_transmits;
569   u->us_clientstate = UPAPCS_AUTHREQ;
570 }
571
572
573 /*
574  * upap_sresp - Send a response (ack or nak).
575  */
576 static void
577 upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen)
578 {
579   u_char *outp;
580   int outlen;
581
582   outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
583   outp = outpacket_buf[u->us_unit];
584   MAKEHEADER(outp, PPP_PAP);
585
586   PUTCHAR(code, outp);
587   PUTCHAR(id, outp);
588   PUTSHORT(outlen, outp);
589   PUTCHAR(msglen, outp);
590   BCOPY(msg, outp, msglen);
591   pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
592
593   UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate));
594 }
595
596 #if 0
597 /*
598  * upap_printpkt - print the contents of a PAP packet.
599  */
600 static int upap_printpkt(
601   u_char *p,
602   int plen,
603   void (*printer) (void *, char *, ...),
604   void *arg
605 )
606 {
607   LWIP_UNUSED_ARG(p);
608   LWIP_UNUSED_ARG(plen);
609   LWIP_UNUSED_ARG(printer);
610   LWIP_UNUSED_ARG(arg);
611   return 0;
612 }
613 #endif /* 0 */
614
615 #endif /* PAP_SUPPORT */
616
617 #endif /* PPP_SUPPORT */