source: S-port/trunk/Middlewares/Third_Party/LwIP/src/netif/ppp/upap.c

Last change on this file was 1, checked in by AlexLir, 3 years ago
File size: 17.6 KB
Line 
1/*
2 * upap.c - User/Password Authentication Protocol.
3 *
4 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * 3. The name "Carnegie Mellon University" must not be used to
19 * endorse or promote products derived from this software without
20 * prior written permission. For permission or any legal
21 * details, please contact
22 * Office of Technology Transfer
23 * Carnegie Mellon University
24 * 5000 Forbes Avenue
25 * Pittsburgh, PA 15213-3890
26 * (412) 268-4387, fax: (412) 268-7395
27 * tech-transfer@andrew.cmu.edu
28 *
29 * 4. Redistributions of any form whatsoever must retain the following
30 * acknowledgment:
31 * "This product includes software developed by Computing Services
32 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33 *
34 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41 */
42
43#include "netif/ppp/ppp_opts.h"
44#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
45
46/*
47 * @todo:
48 */
49
50#if 0 /* UNUSED */
51#include <stdio.h>
52#include <string.h>
53#endif /* UNUSED */
54
55#include "netif/ppp/ppp_impl.h"
56
57#include "netif/ppp/upap.h"
58
59#if PPP_OPTIONS
60/*
61 * Command-line options.
62 */
63static option_t pap_option_list[] = {
64 { "hide-password", o_bool, &hide_password,
65 "Don't output passwords to log", OPT_PRIO | 1 },
66 { "show-password", o_bool, &hide_password,
67 "Show password string in debug log messages", OPT_PRIOSUB | 0 },
68
69 { "pap-restart", o_int, &upap[0].us_timeouttime,
70 "Set retransmit timeout for PAP", OPT_PRIO },
71 { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
72 "Set max number of transmissions for auth-reqs", OPT_PRIO },
73 { "pap-timeout", o_int, &upap[0].us_reqtimeout,
74 "Set time limit for peer PAP authentication", OPT_PRIO },
75
76 { NULL }
77};
78#endif /* PPP_OPTIONS */
79
80/*
81 * Protocol entry points.
82 */
83static void upap_init(ppp_pcb *pcb);
84static void upap_lowerup(ppp_pcb *pcb);
85static void upap_lowerdown(ppp_pcb *pcb);
86static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l);
87static void upap_protrej(ppp_pcb *pcb);
88#if PRINTPKT_SUPPORT
89static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg);
90#endif /* PRINTPKT_SUPPORT */
91
92const struct protent pap_protent = {
93 PPP_PAP,
94 upap_init,
95 upap_input,
96 upap_protrej,
97 upap_lowerup,
98 upap_lowerdown,
99 NULL,
100 NULL,
101#if PRINTPKT_SUPPORT
102 upap_printpkt,
103#endif /* PRINTPKT_SUPPORT */
104#if PPP_DATAINPUT
105 NULL,
106#endif /* PPP_DATAINPUT */
107#if PRINTPKT_SUPPORT
108 "PAP",
109 NULL,
110#endif /* PRINTPKT_SUPPORT */
111#if PPP_OPTIONS
112 pap_option_list,
113 NULL,
114#endif /* PPP_OPTIONS */
115#if DEMAND_SUPPORT
116 NULL,
117 NULL
118#endif /* DEMAND_SUPPORT */
119};
120
121static void upap_timeout(void *arg);
122#if PPP_SERVER
123static void upap_reqtimeout(void *arg);
124static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len);
125#endif /* PPP_SERVER */
126static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len);
127static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len);
128static void upap_sauthreq(ppp_pcb *pcb);
129#if PPP_SERVER
130static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen);
131#endif /* PPP_SERVER */
132
133
134/*
135 * upap_init - Initialize a UPAP unit.
136 */
137static void upap_init(ppp_pcb *pcb) {
138 pcb->upap.us_user = NULL;
139 pcb->upap.us_userlen = 0;
140 pcb->upap.us_passwd = NULL;
141 pcb->upap.us_passwdlen = 0;
142 pcb->upap.us_clientstate = UPAPCS_INITIAL;
143#if PPP_SERVER
144 pcb->upap.us_serverstate = UPAPSS_INITIAL;
145#endif /* PPP_SERVER */
146 pcb->upap.us_id = 0;
147}
148
149
150/*
151 * upap_authwithpeer - Authenticate us with our peer (start client).
152 *
153 * Set new state and send authenticate's.
154 */
155void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) {
156
157 if(!user || !password)
158 return;
159
160 /* Save the username and password we're given */
161 pcb->upap.us_user = user;
162 pcb->upap.us_userlen = (u8_t)LWIP_MIN(strlen(user), 0xff);
163 pcb->upap.us_passwd = password;
164 pcb->upap.us_passwdlen = (u8_t)LWIP_MIN(strlen(password), 0xff);
165 pcb->upap.us_transmits = 0;
166
167 /* Lower layer up yet? */
168 if (pcb->upap.us_clientstate == UPAPCS_INITIAL ||
169 pcb->upap.us_clientstate == UPAPCS_PENDING) {
170 pcb->upap.us_clientstate = UPAPCS_PENDING;
171 return;
172 }
173
174 upap_sauthreq(pcb); /* Start protocol */
175}
176
177#if PPP_SERVER
178/*
179 * upap_authpeer - Authenticate our peer (start server).
180 *
181 * Set new state.
182 */
183void upap_authpeer(ppp_pcb *pcb) {
184
185 /* Lower layer up yet? */
186 if (pcb->upap.us_serverstate == UPAPSS_INITIAL ||
187 pcb->upap.us_serverstate == UPAPSS_PENDING) {
188 pcb->upap.us_serverstate = UPAPSS_PENDING;
189 return;
190 }
191
192 pcb->upap.us_serverstate = UPAPSS_LISTEN;
193 if (pcb->settings.pap_req_timeout > 0)
194 TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
195}
196#endif /* PPP_SERVER */
197
198/*
199 * upap_timeout - Retransmission timer for sending auth-reqs expired.
200 */
201static void upap_timeout(void *arg) {
202 ppp_pcb *pcb = (ppp_pcb*)arg;
203
204 if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ)
205 return;
206
207 if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) {
208 /* give up in disgust */
209 ppp_error("No response to PAP authenticate-requests");
210 pcb->upap.us_clientstate = UPAPCS_BADAUTH;
211 auth_withpeer_fail(pcb, PPP_PAP);
212 return;
213 }
214
215 upap_sauthreq(pcb); /* Send Authenticate-Request */
216}
217
218
219#if PPP_SERVER
220/*
221 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
222 */
223static void upap_reqtimeout(void *arg) {
224 ppp_pcb *pcb = (ppp_pcb*)arg;
225
226 if (pcb->upap.us_serverstate != UPAPSS_LISTEN)
227 return; /* huh?? */
228
229 auth_peer_fail(pcb, PPP_PAP);
230 pcb->upap.us_serverstate = UPAPSS_BADAUTH;
231}
232#endif /* PPP_SERVER */
233
234
235/*
236 * upap_lowerup - The lower layer is up.
237 *
238 * Start authenticating if pending.
239 */
240static void upap_lowerup(ppp_pcb *pcb) {
241
242 if (pcb->upap.us_clientstate == UPAPCS_INITIAL)
243 pcb->upap.us_clientstate = UPAPCS_CLOSED;
244 else if (pcb->upap.us_clientstate == UPAPCS_PENDING) {
245 upap_sauthreq(pcb); /* send an auth-request */
246 }
247
248#if PPP_SERVER
249 if (pcb->upap.us_serverstate == UPAPSS_INITIAL)
250 pcb->upap.us_serverstate = UPAPSS_CLOSED;
251 else if (pcb->upap.us_serverstate == UPAPSS_PENDING) {
252 pcb->upap.us_serverstate = UPAPSS_LISTEN;
253 if (pcb->settings.pap_req_timeout > 0)
254 TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
255 }
256#endif /* PPP_SERVER */
257}
258
259
260/*
261 * upap_lowerdown - The lower layer is down.
262 *
263 * Cancel all timeouts.
264 */
265static void upap_lowerdown(ppp_pcb *pcb) {
266
267 if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
268 UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */
269#if PPP_SERVER
270 if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0)
271 UNTIMEOUT(upap_reqtimeout, pcb);
272#endif /* PPP_SERVER */
273
274 pcb->upap.us_clientstate = UPAPCS_INITIAL;
275#if PPP_SERVER
276 pcb->upap.us_serverstate = UPAPSS_INITIAL;
277#endif /* PPP_SERVER */
278}
279
280
281/*
282 * upap_protrej - Peer doesn't speak this protocol.
283 *
284 * This shouldn't happen. In any case, pretend lower layer went down.
285 */
286static void upap_protrej(ppp_pcb *pcb) {
287
288 if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) {
289 ppp_error("PAP authentication failed due to protocol-reject");
290 auth_withpeer_fail(pcb, PPP_PAP);
291 }
292#if PPP_SERVER
293 if (pcb->upap.us_serverstate == UPAPSS_LISTEN) {
294 ppp_error("PAP authentication of peer failed (protocol-reject)");
295 auth_peer_fail(pcb, PPP_PAP);
296 }
297#endif /* PPP_SERVER */
298 upap_lowerdown(pcb);
299}
300
301
302/*
303 * upap_input - Input UPAP packet.
304 */
305static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) {
306 u_char *inp;
307 u_char code, id;
308 int len;
309
310 /*
311 * Parse header (code, id and length).
312 * If packet too short, drop it.
313 */
314 inp = inpacket;
315 if (l < UPAP_HEADERLEN) {
316 UPAPDEBUG(("pap_input: rcvd short header."));
317 return;
318 }
319 GETCHAR(code, inp);
320 GETCHAR(id, inp);
321 GETSHORT(len, inp);
322 if (len < UPAP_HEADERLEN) {
323 UPAPDEBUG(("pap_input: rcvd illegal length."));
324 return;
325 }
326 if (len > l) {
327 UPAPDEBUG(("pap_input: rcvd short packet."));
328 return;
329 }
330 len -= UPAP_HEADERLEN;
331
332 /*
333 * Action depends on code.
334 */
335 switch (code) {
336 case UPAP_AUTHREQ:
337#if PPP_SERVER
338 upap_rauthreq(pcb, inp, id, len);
339#endif /* PPP_SERVER */
340 break;
341
342 case UPAP_AUTHACK:
343 upap_rauthack(pcb, inp, id, len);
344 break;
345
346 case UPAP_AUTHNAK:
347 upap_rauthnak(pcb, inp, id, len);
348 break;
349
350 default: /* XXX Need code reject */
351 break;
352 }
353}
354
355#if PPP_SERVER
356/*
357 * upap_rauth - Receive Authenticate.
358 */
359static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) {
360 u_char ruserlen, rpasswdlen;
361 char *ruser;
362 char *rpasswd;
363 char rhostname[256];
364 int retcode;
365 const char *msg;
366 int msglen;
367
368 if (pcb->upap.us_serverstate < UPAPSS_LISTEN)
369 return;
370
371 /*
372 * If we receive a duplicate authenticate-request, we are
373 * supposed to return the same status as for the first request.
374 */
375 if (pcb->upap.us_serverstate == UPAPSS_OPEN) {
376 upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
377 return;
378 }
379 if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) {
380 upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
381 return;
382 }
383
384 /*
385 * Parse user/passwd.
386 */
387 if (len < 1) {
388 UPAPDEBUG(("pap_rauth: rcvd short packet."));
389 return;
390 }
391 GETCHAR(ruserlen, inp);
392 len -= sizeof (u_char) + ruserlen + sizeof (u_char);
393 if (len < 0) {
394 UPAPDEBUG(("pap_rauth: rcvd short packet."));
395 return;
396 }
397 ruser = (char *) inp;
398 INCPTR(ruserlen, inp);
399 GETCHAR(rpasswdlen, inp);
400 if (len < rpasswdlen) {
401 UPAPDEBUG(("pap_rauth: rcvd short packet."));
402 return;
403 }
404
405 rpasswd = (char *) inp;
406
407 /*
408 * Check the username and password given.
409 */
410 retcode = UPAP_AUTHNAK;
411 if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) {
412 retcode = UPAP_AUTHACK;
413 }
414 BZERO(rpasswd, rpasswdlen);
415
416#if 0 /* UNUSED */
417 /*
418 * Check remote number authorization. A plugin may have filled in
419 * the remote number or added an allowed number, and rather than
420 * return an authenticate failure, is leaving it for us to verify.
421 */
422 if (retcode == UPAP_AUTHACK) {
423 if (!auth_number()) {
424 /* We do not want to leak info about the pap result. */
425 retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */
426 warn("calling number %q is not authorized", remote_number);
427 }
428 }
429
430 msglen = strlen(msg);
431 if (msglen > 255)
432 msglen = 255;
433#endif /* UNUSED */
434
435 upap_sresp(pcb, retcode, id, msg, msglen);
436
437 /* Null terminate and clean remote name. */
438 ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser);
439
440 if (retcode == UPAP_AUTHACK) {
441 pcb->upap.us_serverstate = UPAPSS_OPEN;
442 ppp_notice("PAP peer authentication succeeded for %q", rhostname);
443 auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen);
444 } else {
445 pcb->upap.us_serverstate = UPAPSS_BADAUTH;
446 ppp_warn("PAP peer authentication failed for %q", rhostname);
447 auth_peer_fail(pcb, PPP_PAP);
448 }
449
450 if (pcb->settings.pap_req_timeout > 0)
451 UNTIMEOUT(upap_reqtimeout, pcb);
452}
453#endif /* PPP_SERVER */
454
455/*
456 * upap_rauthack - Receive Authenticate-Ack.
457 */
458static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) {
459 u_char msglen;
460 char *msg;
461 LWIP_UNUSED_ARG(id);
462
463 if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
464 return;
465
466 /*
467 * Parse message.
468 */
469 if (len < 1) {
470 UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
471 } else {
472 GETCHAR(msglen, inp);
473 if (msglen > 0) {
474 len -= sizeof (u_char);
475 if (len < msglen) {
476 UPAPDEBUG(("pap_rauthack: rcvd short packet."));
477 return;
478 }
479 msg = (char *) inp;
480 PRINTMSG(msg, msglen);
481 }
482 }
483
484 pcb->upap.us_clientstate = UPAPCS_OPEN;
485
486 auth_withpeer_success(pcb, PPP_PAP, 0);
487}
488
489
490/*
491 * upap_rauthnak - Receive Authenticate-Nak.
492 */
493static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) {
494 u_char msglen;
495 char *msg;
496 LWIP_UNUSED_ARG(id);
497
498 if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
499 return;
500
501 /*
502 * Parse message.
503 */
504 if (len < 1) {
505 UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
506 } else {
507 GETCHAR(msglen, inp);
508 if (msglen > 0) {
509 len -= sizeof (u_char);
510 if (len < msglen) {
511 UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
512 return;
513 }
514 msg = (char *) inp;
515 PRINTMSG(msg, msglen);
516 }
517 }
518
519 pcb->upap.us_clientstate = UPAPCS_BADAUTH;
520
521 ppp_error("PAP authentication failed");
522 auth_withpeer_fail(pcb, PPP_PAP);
523}
524
525
526/*
527 * upap_sauthreq - Send an Authenticate-Request.
528 */
529static void upap_sauthreq(ppp_pcb *pcb) {
530 struct pbuf *p;
531 u_char *outp;
532 int outlen;
533
534 outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
535 pcb->upap.us_userlen + pcb->upap.us_passwdlen;
536 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
537 if(NULL == p)
538 return;
539 if(p->tot_len != p->len) {
540 pbuf_free(p);
541 return;
542 }
543
544 outp = (u_char*)p->payload;
545 MAKEHEADER(outp, PPP_PAP);
546
547 PUTCHAR(UPAP_AUTHREQ, outp);
548 PUTCHAR(++pcb->upap.us_id, outp);
549 PUTSHORT(outlen, outp);
550 PUTCHAR(pcb->upap.us_userlen, outp);
551 MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen);
552 INCPTR(pcb->upap.us_userlen, outp);
553 PUTCHAR(pcb->upap.us_passwdlen, outp);
554 MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen);
555
556 ppp_write(pcb, p);
557
558 TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time);
559 ++pcb->upap.us_transmits;
560 pcb->upap.us_clientstate = UPAPCS_AUTHREQ;
561}
562
563#if PPP_SERVER
564/*
565 * upap_sresp - Send a response (ack or nak).
566 */
567static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) {
568 struct pbuf *p;
569 u_char *outp;
570 int outlen;
571
572 outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
573 p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
574 if(NULL == p)
575 return;
576 if(p->tot_len != p->len) {
577 pbuf_free(p);
578 return;
579 }
580
581 outp = (u_char*)p->payload;
582 MAKEHEADER(outp, PPP_PAP);
583
584 PUTCHAR(code, outp);
585 PUTCHAR(id, outp);
586 PUTSHORT(outlen, outp);
587 PUTCHAR(msglen, outp);
588 MEMCPY(outp, msg, msglen);
589
590 ppp_write(pcb, p);
591}
592#endif /* PPP_SERVER */
593
594#if PRINTPKT_SUPPORT
595/*
596 * upap_printpkt - print the contents of a PAP packet.
597 */
598static const char* const upap_codenames[] = {
599 "AuthReq", "AuthAck", "AuthNak"
600};
601
602static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) {
603 int code, id, len;
604 int mlen, ulen, wlen;
605 const u_char *user, *pwd, *msg;
606 const u_char *pstart;
607
608 if (plen < UPAP_HEADERLEN)
609 return 0;
610 pstart = p;
611 GETCHAR(code, p);
612 GETCHAR(id, p);
613 GETSHORT(len, p);
614 if (len < UPAP_HEADERLEN || len > plen)
615 return 0;
616
617 if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames))
618 printer(arg, " %s", upap_codenames[code-1]);
619 else
620 printer(arg, " code=0x%x", code);
621 printer(arg, " id=0x%x", id);
622 len -= UPAP_HEADERLEN;
623 switch (code) {
624 case UPAP_AUTHREQ:
625 if (len < 1)
626 break;
627 ulen = p[0];
628 if (len < ulen + 2)
629 break;
630 wlen = p[ulen + 1];
631 if (len < ulen + wlen + 2)
632 break;
633 user = (const u_char *) (p + 1);
634 pwd = (const u_char *) (p + ulen + 2);
635 p += ulen + wlen + 2;
636 len -= ulen + wlen + 2;
637 printer(arg, " user=");
638 ppp_print_string(user, ulen, printer, arg);
639 printer(arg, " password=");
640/* FIXME: require ppp_pcb struct as printpkt() argument */
641#if 0
642 if (!pcb->settings.hide_password)
643#endif
644 ppp_print_string(pwd, wlen, printer, arg);
645#if 0
646 else
647 printer(arg, "<hidden>");
648#endif
649 break;
650 case UPAP_AUTHACK:
651 case UPAP_AUTHNAK:
652 if (len < 1)
653 break;
654 mlen = p[0];
655 if (len < mlen + 1)
656 break;
657 msg = (const u_char *) (p + 1);
658 p += mlen + 1;
659 len -= mlen + 1;
660 printer(arg, " ");
661 ppp_print_string(msg, mlen, printer, arg);
662 break;
663 default:
664 break;
665 }
666
667 /* print the rest of the bytes in the packet */
668 for (; len > 0; --len) {
669 GETCHAR(code, p);
670 printer(arg, " %.2x", code);
671 }
672
673 return p - pstart;
674}
675#endif /* PRINTPKT_SUPPORT */
676
677#endif /* PPP_SUPPORT && PAP_SUPPORT */
Note: See TracBrowser for help on using the repository browser.