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  */
63 static 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  */
83 static void upap_init(ppp_pcb *pcb);
84 static void upap_lowerup(ppp_pcb *pcb);
85 static void upap_lowerdown(ppp_pcb *pcb);
86 static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l);
87 static void upap_protrej(ppp_pcb *pcb);
88 #if PRINTPKT_SUPPORT
89 static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg);
90 #endif /* PRINTPKT_SUPPORT */
91 
92 const 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 
121 static void upap_timeout(void *arg);
122 #if PPP_SERVER
123 static void upap_reqtimeout(void *arg);
124 static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len);
125 #endif /* PPP_SERVER */
126 static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len);
127 static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len);
128 static void upap_sauthreq(ppp_pcb *pcb);
129 #if PPP_SERVER
130 static 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  */
upap_init(ppp_pcb * pcb)137 static 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  */
upap_authwithpeer(ppp_pcb * pcb,const char * user,const char * password)155 void 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  */
upap_authpeer(ppp_pcb * pcb)183 void 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  */
upap_timeout(void * arg)201 static 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  */
upap_reqtimeout(void * arg)223 static 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  */
upap_lowerup(ppp_pcb * pcb)240 static 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  */
upap_lowerdown(ppp_pcb * pcb)265 static 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  */
upap_protrej(ppp_pcb * pcb)286 static 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  */
upap_input(ppp_pcb * pcb,u_char * inpacket,int l)305 static 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  */
upap_rauthreq(ppp_pcb * pcb,u_char * inp,int id,int len)359 static 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  */
upap_rauthack(ppp_pcb * pcb,u_char * inp,int id,int len)458 static 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     UNTIMEOUT(upap_timeout, pcb);
485     pcb->upap.us_clientstate = UPAPCS_OPEN;
486 
487     auth_withpeer_success(pcb, PPP_PAP, 0);
488 }
489 
490 
491 /*
492  * upap_rauthnak - Receive Authenticate-Nak.
493  */
upap_rauthnak(ppp_pcb * pcb,u_char * inp,int id,int len)494 static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) {
495     u_char msglen;
496     char *msg;
497     LWIP_UNUSED_ARG(id);
498 
499     if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
500 	return;
501 
502     /*
503      * Parse message.
504      */
505     if (len < 1) {
506 	UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
507     } else {
508 	GETCHAR(msglen, inp);
509 	if (msglen > 0) {
510 	    len -= sizeof (u_char);
511 	    if (len < msglen) {
512 		UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
513 		return;
514 	    }
515 	    msg = (char *) inp;
516 	    PRINTMSG(msg, msglen);
517 	}
518     }
519 
520     UNTIMEOUT(upap_timeout, pcb);
521     pcb->upap.us_clientstate = UPAPCS_BADAUTH;
522 
523     ppp_error(("PAP authentication failed"));
524     auth_withpeer_fail(pcb, PPP_PAP);
525 }
526 
527 
528 /*
529  * upap_sauthreq - Send an Authenticate-Request.
530  */
upap_sauthreq(ppp_pcb * pcb)531 static void upap_sauthreq(ppp_pcb *pcb) {
532     struct pbuf *p;
533     u_char *outp;
534     int outlen;
535 
536     outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
537 	pcb->upap.us_userlen + pcb->upap.us_passwdlen;
538     p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PBUF_RAM);
539     if(NULL == p)
540         return;
541     if(p->tot_len != p->len) {
542         pbuf_free(p);
543         return;
544     }
545 
546     outp = (u_char*)p->payload;
547     MAKEHEADER(outp, PPP_PAP);
548 
549     PUTCHAR(UPAP_AUTHREQ, outp);
550     PUTCHAR(++pcb->upap.us_id, outp);
551     PUTSHORT(outlen, outp);
552     PUTCHAR(pcb->upap.us_userlen, outp);
553     MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen);
554     INCPTR(pcb->upap.us_userlen, outp);
555     PUTCHAR(pcb->upap.us_passwdlen, outp);
556     MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen);
557 
558     ppp_write(pcb, p);
559 
560     TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time);
561     ++pcb->upap.us_transmits;
562     pcb->upap.us_clientstate = UPAPCS_AUTHREQ;
563 }
564 
565 #if PPP_SERVER
566 /*
567  * upap_sresp - Send a response (ack or nak).
568  */
upap_sresp(ppp_pcb * pcb,u_char code,u_char id,const char * msg,int msglen)569 static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) {
570     struct pbuf *p;
571     u_char *outp;
572     int outlen;
573 
574     outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
575     p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PBUF_RAM);
576     if(NULL == p)
577         return;
578     if(p->tot_len != p->len) {
579         pbuf_free(p);
580         return;
581     }
582 
583     outp = (u_char*)p->payload;
584     MAKEHEADER(outp, PPP_PAP);
585 
586     PUTCHAR(code, outp);
587     PUTCHAR(id, outp);
588     PUTSHORT(outlen, outp);
589     PUTCHAR(msglen, outp);
590     MEMCPY(outp, msg, msglen);
591 
592     ppp_write(pcb, p);
593 }
594 #endif /* PPP_SERVER */
595 
596 #if PRINTPKT_SUPPORT
597 /*
598  * upap_printpkt - print the contents of a PAP packet.
599  */
600 static const char* const upap_codenames[] = {
601     "AuthReq", "AuthAck", "AuthNak"
602 };
603 
upap_printpkt(const u_char * p,int plen,void (* printer)(void *,const char *,...),void * arg)604 static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) {
605     int code, id, len;
606     int mlen, ulen, wlen;
607     const u_char *user, *pwd, *msg;
608     const u_char *pstart;
609 
610     if (plen < UPAP_HEADERLEN)
611 	return 0;
612     pstart = p;
613     GETCHAR(code, p);
614     GETCHAR(id, p);
615     GETSHORT(len, p);
616     if (len < UPAP_HEADERLEN || len > plen)
617 	return 0;
618 
619     if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames))
620 	printer(arg, " %s", upap_codenames[code-1]);
621     else
622 	printer(arg, " code=0x%x", code);
623     printer(arg, " id=0x%x", id);
624     len -= UPAP_HEADERLEN;
625     switch (code) {
626     case UPAP_AUTHREQ:
627 	if (len < 1)
628 	    break;
629 	ulen = p[0];
630 	if (len < ulen + 2)
631 	    break;
632 	wlen = p[ulen + 1];
633 	if (len < ulen + wlen + 2)
634 	    break;
635 	user = (const u_char *) (p + 1);
636 	pwd = (const u_char *) (p + ulen + 2);
637 	p += ulen + wlen + 2;
638 	len -= ulen + wlen + 2;
639 	printer(arg, " user=");
640 	ppp_print_string(user, ulen, printer, arg);
641 	printer(arg, " password=");
642 /* FIXME: require ppp_pcb struct as printpkt() argument */
643 #if 0
644 	if (!pcb->settings.hide_password)
645 #endif
646 	    ppp_print_string(pwd, wlen, printer, arg);
647 #if 0
648 	else
649 	    printer(arg, "<hidden>");
650 #endif
651 	break;
652     case UPAP_AUTHACK:
653     case UPAP_AUTHNAK:
654 	if (len < 1)
655 	    break;
656 	mlen = p[0];
657 	if (len < mlen + 1)
658 	    break;
659 	msg = (const u_char *) (p + 1);
660 	p += mlen + 1;
661 	len -= mlen + 1;
662 	printer(arg, " ");
663 	ppp_print_string(msg, mlen, printer, arg);
664 	break;
665     default:
666 	break;
667     }
668 
669     /* print the rest of the bytes in the packet */
670     for (; len > 0; --len) {
671 	GETCHAR(code, p);
672 	printer(arg, " %.2x", code);
673     }
674 
675     return p - pstart;
676 }
677 #endif /* PRINTPKT_SUPPORT */
678 
679 #endif /* PPP_SUPPORT && PAP_SUPPORT */
680