1195972f6Sopenharmony_ci/* 2195972f6Sopenharmony_ci * upap.c - User/Password Authentication Protocol. 3195972f6Sopenharmony_ci * 4195972f6Sopenharmony_ci * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 5195972f6Sopenharmony_ci * 6195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 7195972f6Sopenharmony_ci * modification, are permitted provided that the following conditions 8195972f6Sopenharmony_ci * are met: 9195972f6Sopenharmony_ci * 10195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 11195972f6Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 12195972f6Sopenharmony_ci * 13195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 14195972f6Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 15195972f6Sopenharmony_ci * the documentation and/or other materials provided with the 16195972f6Sopenharmony_ci * distribution. 17195972f6Sopenharmony_ci * 18195972f6Sopenharmony_ci * 3. The name "Carnegie Mellon University" must not be used to 19195972f6Sopenharmony_ci * endorse or promote products derived from this software without 20195972f6Sopenharmony_ci * prior written permission. For permission or any legal 21195972f6Sopenharmony_ci * details, please contact 22195972f6Sopenharmony_ci * Office of Technology Transfer 23195972f6Sopenharmony_ci * Carnegie Mellon University 24195972f6Sopenharmony_ci * 5000 Forbes Avenue 25195972f6Sopenharmony_ci * Pittsburgh, PA 15213-3890 26195972f6Sopenharmony_ci * (412) 268-4387, fax: (412) 268-7395 27195972f6Sopenharmony_ci * tech-transfer@andrew.cmu.edu 28195972f6Sopenharmony_ci * 29195972f6Sopenharmony_ci * 4. Redistributions of any form whatsoever must retain the following 30195972f6Sopenharmony_ci * acknowledgment: 31195972f6Sopenharmony_ci * "This product includes software developed by Computing Services 32195972f6Sopenharmony_ci * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 33195972f6Sopenharmony_ci * 34195972f6Sopenharmony_ci * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 35195972f6Sopenharmony_ci * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 36195972f6Sopenharmony_ci * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 37195972f6Sopenharmony_ci * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 38195972f6Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 39195972f6Sopenharmony_ci * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 40195972f6Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 41195972f6Sopenharmony_ci */ 42195972f6Sopenharmony_ci 43195972f6Sopenharmony_ci#include "netif/ppp/ppp_opts.h" 44195972f6Sopenharmony_ci#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 45195972f6Sopenharmony_ci 46195972f6Sopenharmony_ci/* 47195972f6Sopenharmony_ci * @todo: 48195972f6Sopenharmony_ci */ 49195972f6Sopenharmony_ci 50195972f6Sopenharmony_ci#if 0 /* UNUSED */ 51195972f6Sopenharmony_ci#include <stdio.h> 52195972f6Sopenharmony_ci#include <string.h> 53195972f6Sopenharmony_ci#endif /* UNUSED */ 54195972f6Sopenharmony_ci 55195972f6Sopenharmony_ci#include "netif/ppp/ppp_impl.h" 56195972f6Sopenharmony_ci 57195972f6Sopenharmony_ci#include "netif/ppp/upap.h" 58195972f6Sopenharmony_ci 59195972f6Sopenharmony_ci#if PPP_OPTIONS 60195972f6Sopenharmony_ci/* 61195972f6Sopenharmony_ci * Command-line options. 62195972f6Sopenharmony_ci */ 63195972f6Sopenharmony_cistatic option_t pap_option_list[] = { 64195972f6Sopenharmony_ci { "hide-password", o_bool, &hide_password, 65195972f6Sopenharmony_ci "Don't output passwords to log", OPT_PRIO | 1 }, 66195972f6Sopenharmony_ci { "show-password", o_bool, &hide_password, 67195972f6Sopenharmony_ci "Show password string in debug log messages", OPT_PRIOSUB | 0 }, 68195972f6Sopenharmony_ci 69195972f6Sopenharmony_ci { "pap-restart", o_int, &upap[0].us_timeouttime, 70195972f6Sopenharmony_ci "Set retransmit timeout for PAP", OPT_PRIO }, 71195972f6Sopenharmony_ci { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, 72195972f6Sopenharmony_ci "Set max number of transmissions for auth-reqs", OPT_PRIO }, 73195972f6Sopenharmony_ci { "pap-timeout", o_int, &upap[0].us_reqtimeout, 74195972f6Sopenharmony_ci "Set time limit for peer PAP authentication", OPT_PRIO }, 75195972f6Sopenharmony_ci 76195972f6Sopenharmony_ci { NULL } 77195972f6Sopenharmony_ci}; 78195972f6Sopenharmony_ci#endif /* PPP_OPTIONS */ 79195972f6Sopenharmony_ci 80195972f6Sopenharmony_ci/* 81195972f6Sopenharmony_ci * Protocol entry points. 82195972f6Sopenharmony_ci */ 83195972f6Sopenharmony_cistatic void upap_init(ppp_pcb *pcb); 84195972f6Sopenharmony_cistatic void upap_lowerup(ppp_pcb *pcb); 85195972f6Sopenharmony_cistatic void upap_lowerdown(ppp_pcb *pcb); 86195972f6Sopenharmony_cistatic void upap_input(ppp_pcb *pcb, u_char *inpacket, int l); 87195972f6Sopenharmony_cistatic void upap_protrej(ppp_pcb *pcb); 88195972f6Sopenharmony_ci#if PRINTPKT_SUPPORT 89195972f6Sopenharmony_cistatic int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); 90195972f6Sopenharmony_ci#endif /* PRINTPKT_SUPPORT */ 91195972f6Sopenharmony_ci 92195972f6Sopenharmony_ciconst struct protent pap_protent = { 93195972f6Sopenharmony_ci PPP_PAP, 94195972f6Sopenharmony_ci upap_init, 95195972f6Sopenharmony_ci upap_input, 96195972f6Sopenharmony_ci upap_protrej, 97195972f6Sopenharmony_ci upap_lowerup, 98195972f6Sopenharmony_ci upap_lowerdown, 99195972f6Sopenharmony_ci NULL, 100195972f6Sopenharmony_ci NULL, 101195972f6Sopenharmony_ci#if PRINTPKT_SUPPORT 102195972f6Sopenharmony_ci upap_printpkt, 103195972f6Sopenharmony_ci#endif /* PRINTPKT_SUPPORT */ 104195972f6Sopenharmony_ci#if PPP_DATAINPUT 105195972f6Sopenharmony_ci NULL, 106195972f6Sopenharmony_ci#endif /* PPP_DATAINPUT */ 107195972f6Sopenharmony_ci#if PRINTPKT_SUPPORT 108195972f6Sopenharmony_ci "PAP", 109195972f6Sopenharmony_ci NULL, 110195972f6Sopenharmony_ci#endif /* PRINTPKT_SUPPORT */ 111195972f6Sopenharmony_ci#if PPP_OPTIONS 112195972f6Sopenharmony_ci pap_option_list, 113195972f6Sopenharmony_ci NULL, 114195972f6Sopenharmony_ci#endif /* PPP_OPTIONS */ 115195972f6Sopenharmony_ci#if DEMAND_SUPPORT 116195972f6Sopenharmony_ci NULL, 117195972f6Sopenharmony_ci NULL 118195972f6Sopenharmony_ci#endif /* DEMAND_SUPPORT */ 119195972f6Sopenharmony_ci}; 120195972f6Sopenharmony_ci 121195972f6Sopenharmony_cistatic void upap_timeout(void *arg); 122195972f6Sopenharmony_ci#if PPP_SERVER 123195972f6Sopenharmony_cistatic void upap_reqtimeout(void *arg); 124195972f6Sopenharmony_cistatic void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len); 125195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 126195972f6Sopenharmony_cistatic void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len); 127195972f6Sopenharmony_cistatic void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len); 128195972f6Sopenharmony_cistatic void upap_sauthreq(ppp_pcb *pcb); 129195972f6Sopenharmony_ci#if PPP_SERVER 130195972f6Sopenharmony_cistatic void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen); 131195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 132195972f6Sopenharmony_ci 133195972f6Sopenharmony_ci 134195972f6Sopenharmony_ci/* 135195972f6Sopenharmony_ci * upap_init - Initialize a UPAP unit. 136195972f6Sopenharmony_ci */ 137195972f6Sopenharmony_cistatic void upap_init(ppp_pcb *pcb) { 138195972f6Sopenharmony_ci pcb->upap.us_user = NULL; 139195972f6Sopenharmony_ci pcb->upap.us_userlen = 0; 140195972f6Sopenharmony_ci pcb->upap.us_passwd = NULL; 141195972f6Sopenharmony_ci pcb->upap.us_passwdlen = 0; 142195972f6Sopenharmony_ci pcb->upap.us_clientstate = UPAPCS_INITIAL; 143195972f6Sopenharmony_ci#if PPP_SERVER 144195972f6Sopenharmony_ci pcb->upap.us_serverstate = UPAPSS_INITIAL; 145195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 146195972f6Sopenharmony_ci pcb->upap.us_id = 0; 147195972f6Sopenharmony_ci} 148195972f6Sopenharmony_ci 149195972f6Sopenharmony_ci 150195972f6Sopenharmony_ci/* 151195972f6Sopenharmony_ci * upap_authwithpeer - Authenticate us with our peer (start client). 152195972f6Sopenharmony_ci * 153195972f6Sopenharmony_ci * Set new state and send authenticate's. 154195972f6Sopenharmony_ci */ 155195972f6Sopenharmony_civoid upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) { 156195972f6Sopenharmony_ci 157195972f6Sopenharmony_ci if(!user || !password) 158195972f6Sopenharmony_ci return; 159195972f6Sopenharmony_ci 160195972f6Sopenharmony_ci /* Save the username and password we're given */ 161195972f6Sopenharmony_ci pcb->upap.us_user = user; 162195972f6Sopenharmony_ci pcb->upap.us_userlen = (u8_t)LWIP_MIN(strlen(user), 0xff); 163195972f6Sopenharmony_ci pcb->upap.us_passwd = password; 164195972f6Sopenharmony_ci pcb->upap.us_passwdlen = (u8_t)LWIP_MIN(strlen(password), 0xff); 165195972f6Sopenharmony_ci pcb->upap.us_transmits = 0; 166195972f6Sopenharmony_ci 167195972f6Sopenharmony_ci /* Lower layer up yet? */ 168195972f6Sopenharmony_ci if (pcb->upap.us_clientstate == UPAPCS_INITIAL || 169195972f6Sopenharmony_ci pcb->upap.us_clientstate == UPAPCS_PENDING) { 170195972f6Sopenharmony_ci pcb->upap.us_clientstate = UPAPCS_PENDING; 171195972f6Sopenharmony_ci return; 172195972f6Sopenharmony_ci } 173195972f6Sopenharmony_ci 174195972f6Sopenharmony_ci upap_sauthreq(pcb); /* Start protocol */ 175195972f6Sopenharmony_ci} 176195972f6Sopenharmony_ci 177195972f6Sopenharmony_ci#if PPP_SERVER 178195972f6Sopenharmony_ci/* 179195972f6Sopenharmony_ci * upap_authpeer - Authenticate our peer (start server). 180195972f6Sopenharmony_ci * 181195972f6Sopenharmony_ci * Set new state. 182195972f6Sopenharmony_ci */ 183195972f6Sopenharmony_civoid upap_authpeer(ppp_pcb *pcb) { 184195972f6Sopenharmony_ci 185195972f6Sopenharmony_ci /* Lower layer up yet? */ 186195972f6Sopenharmony_ci if (pcb->upap.us_serverstate == UPAPSS_INITIAL || 187195972f6Sopenharmony_ci pcb->upap.us_serverstate == UPAPSS_PENDING) { 188195972f6Sopenharmony_ci pcb->upap.us_serverstate = UPAPSS_PENDING; 189195972f6Sopenharmony_ci return; 190195972f6Sopenharmony_ci } 191195972f6Sopenharmony_ci 192195972f6Sopenharmony_ci pcb->upap.us_serverstate = UPAPSS_LISTEN; 193195972f6Sopenharmony_ci if (pcb->settings.pap_req_timeout > 0) 194195972f6Sopenharmony_ci TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); 195195972f6Sopenharmony_ci} 196195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 197195972f6Sopenharmony_ci 198195972f6Sopenharmony_ci/* 199195972f6Sopenharmony_ci * upap_timeout - Retransmission timer for sending auth-reqs expired. 200195972f6Sopenharmony_ci */ 201195972f6Sopenharmony_cistatic void upap_timeout(void *arg) { 202195972f6Sopenharmony_ci ppp_pcb *pcb = (ppp_pcb*)arg; 203195972f6Sopenharmony_ci 204195972f6Sopenharmony_ci if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) 205195972f6Sopenharmony_ci return; 206195972f6Sopenharmony_ci 207195972f6Sopenharmony_ci if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) { 208195972f6Sopenharmony_ci /* give up in disgust */ 209195972f6Sopenharmony_ci ppp_error("No response to PAP authenticate-requests"); 210195972f6Sopenharmony_ci pcb->upap.us_clientstate = UPAPCS_BADAUTH; 211195972f6Sopenharmony_ci auth_withpeer_fail(pcb, PPP_PAP); 212195972f6Sopenharmony_ci return; 213195972f6Sopenharmony_ci } 214195972f6Sopenharmony_ci 215195972f6Sopenharmony_ci upap_sauthreq(pcb); /* Send Authenticate-Request */ 216195972f6Sopenharmony_ci} 217195972f6Sopenharmony_ci 218195972f6Sopenharmony_ci 219195972f6Sopenharmony_ci#if PPP_SERVER 220195972f6Sopenharmony_ci/* 221195972f6Sopenharmony_ci * upap_reqtimeout - Give up waiting for the peer to send an auth-req. 222195972f6Sopenharmony_ci */ 223195972f6Sopenharmony_cistatic void upap_reqtimeout(void *arg) { 224195972f6Sopenharmony_ci ppp_pcb *pcb = (ppp_pcb*)arg; 225195972f6Sopenharmony_ci 226195972f6Sopenharmony_ci if (pcb->upap.us_serverstate != UPAPSS_LISTEN) 227195972f6Sopenharmony_ci return; /* huh?? */ 228195972f6Sopenharmony_ci 229195972f6Sopenharmony_ci auth_peer_fail(pcb, PPP_PAP); 230195972f6Sopenharmony_ci pcb->upap.us_serverstate = UPAPSS_BADAUTH; 231195972f6Sopenharmony_ci} 232195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 233195972f6Sopenharmony_ci 234195972f6Sopenharmony_ci 235195972f6Sopenharmony_ci/* 236195972f6Sopenharmony_ci * upap_lowerup - The lower layer is up. 237195972f6Sopenharmony_ci * 238195972f6Sopenharmony_ci * Start authenticating if pending. 239195972f6Sopenharmony_ci */ 240195972f6Sopenharmony_cistatic void upap_lowerup(ppp_pcb *pcb) { 241195972f6Sopenharmony_ci 242195972f6Sopenharmony_ci if (pcb->upap.us_clientstate == UPAPCS_INITIAL) 243195972f6Sopenharmony_ci pcb->upap.us_clientstate = UPAPCS_CLOSED; 244195972f6Sopenharmony_ci else if (pcb->upap.us_clientstate == UPAPCS_PENDING) { 245195972f6Sopenharmony_ci upap_sauthreq(pcb); /* send an auth-request */ 246195972f6Sopenharmony_ci } 247195972f6Sopenharmony_ci 248195972f6Sopenharmony_ci#if PPP_SERVER 249195972f6Sopenharmony_ci if (pcb->upap.us_serverstate == UPAPSS_INITIAL) 250195972f6Sopenharmony_ci pcb->upap.us_serverstate = UPAPSS_CLOSED; 251195972f6Sopenharmony_ci else if (pcb->upap.us_serverstate == UPAPSS_PENDING) { 252195972f6Sopenharmony_ci pcb->upap.us_serverstate = UPAPSS_LISTEN; 253195972f6Sopenharmony_ci if (pcb->settings.pap_req_timeout > 0) 254195972f6Sopenharmony_ci TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); 255195972f6Sopenharmony_ci } 256195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 257195972f6Sopenharmony_ci} 258195972f6Sopenharmony_ci 259195972f6Sopenharmony_ci 260195972f6Sopenharmony_ci/* 261195972f6Sopenharmony_ci * upap_lowerdown - The lower layer is down. 262195972f6Sopenharmony_ci * 263195972f6Sopenharmony_ci * Cancel all timeouts. 264195972f6Sopenharmony_ci */ 265195972f6Sopenharmony_cistatic void upap_lowerdown(ppp_pcb *pcb) { 266195972f6Sopenharmony_ci 267195972f6Sopenharmony_ci if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ 268195972f6Sopenharmony_ci UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */ 269195972f6Sopenharmony_ci#if PPP_SERVER 270195972f6Sopenharmony_ci if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0) 271195972f6Sopenharmony_ci UNTIMEOUT(upap_reqtimeout, pcb); 272195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 273195972f6Sopenharmony_ci 274195972f6Sopenharmony_ci pcb->upap.us_clientstate = UPAPCS_INITIAL; 275195972f6Sopenharmony_ci#if PPP_SERVER 276195972f6Sopenharmony_ci pcb->upap.us_serverstate = UPAPSS_INITIAL; 277195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 278195972f6Sopenharmony_ci} 279195972f6Sopenharmony_ci 280195972f6Sopenharmony_ci 281195972f6Sopenharmony_ci/* 282195972f6Sopenharmony_ci * upap_protrej - Peer doesn't speak this protocol. 283195972f6Sopenharmony_ci * 284195972f6Sopenharmony_ci * This shouldn't happen. In any case, pretend lower layer went down. 285195972f6Sopenharmony_ci */ 286195972f6Sopenharmony_cistatic void upap_protrej(ppp_pcb *pcb) { 287195972f6Sopenharmony_ci 288195972f6Sopenharmony_ci if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) { 289195972f6Sopenharmony_ci ppp_error("PAP authentication failed due to protocol-reject"); 290195972f6Sopenharmony_ci auth_withpeer_fail(pcb, PPP_PAP); 291195972f6Sopenharmony_ci } 292195972f6Sopenharmony_ci#if PPP_SERVER 293195972f6Sopenharmony_ci if (pcb->upap.us_serverstate == UPAPSS_LISTEN) { 294195972f6Sopenharmony_ci ppp_error("PAP authentication of peer failed (protocol-reject)"); 295195972f6Sopenharmony_ci auth_peer_fail(pcb, PPP_PAP); 296195972f6Sopenharmony_ci } 297195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 298195972f6Sopenharmony_ci upap_lowerdown(pcb); 299195972f6Sopenharmony_ci} 300195972f6Sopenharmony_ci 301195972f6Sopenharmony_ci 302195972f6Sopenharmony_ci/* 303195972f6Sopenharmony_ci * upap_input - Input UPAP packet. 304195972f6Sopenharmony_ci */ 305195972f6Sopenharmony_cistatic void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) { 306195972f6Sopenharmony_ci u_char *inp; 307195972f6Sopenharmony_ci u_char code, id; 308195972f6Sopenharmony_ci int len; 309195972f6Sopenharmony_ci 310195972f6Sopenharmony_ci /* 311195972f6Sopenharmony_ci * Parse header (code, id and length). 312195972f6Sopenharmony_ci * If packet too short, drop it. 313195972f6Sopenharmony_ci */ 314195972f6Sopenharmony_ci inp = inpacket; 315195972f6Sopenharmony_ci if (l < UPAP_HEADERLEN) { 316195972f6Sopenharmony_ci UPAPDEBUG(("pap_input: rcvd short header.")); 317195972f6Sopenharmony_ci return; 318195972f6Sopenharmony_ci } 319195972f6Sopenharmony_ci GETCHAR(code, inp); 320195972f6Sopenharmony_ci GETCHAR(id, inp); 321195972f6Sopenharmony_ci GETSHORT(len, inp); 322195972f6Sopenharmony_ci if (len < UPAP_HEADERLEN) { 323195972f6Sopenharmony_ci UPAPDEBUG(("pap_input: rcvd illegal length.")); 324195972f6Sopenharmony_ci return; 325195972f6Sopenharmony_ci } 326195972f6Sopenharmony_ci if (len > l) { 327195972f6Sopenharmony_ci UPAPDEBUG(("pap_input: rcvd short packet.")); 328195972f6Sopenharmony_ci return; 329195972f6Sopenharmony_ci } 330195972f6Sopenharmony_ci len -= UPAP_HEADERLEN; 331195972f6Sopenharmony_ci 332195972f6Sopenharmony_ci /* 333195972f6Sopenharmony_ci * Action depends on code. 334195972f6Sopenharmony_ci */ 335195972f6Sopenharmony_ci switch (code) { 336195972f6Sopenharmony_ci case UPAP_AUTHREQ: 337195972f6Sopenharmony_ci#if PPP_SERVER 338195972f6Sopenharmony_ci upap_rauthreq(pcb, inp, id, len); 339195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 340195972f6Sopenharmony_ci break; 341195972f6Sopenharmony_ci 342195972f6Sopenharmony_ci case UPAP_AUTHACK: 343195972f6Sopenharmony_ci upap_rauthack(pcb, inp, id, len); 344195972f6Sopenharmony_ci break; 345195972f6Sopenharmony_ci 346195972f6Sopenharmony_ci case UPAP_AUTHNAK: 347195972f6Sopenharmony_ci upap_rauthnak(pcb, inp, id, len); 348195972f6Sopenharmony_ci break; 349195972f6Sopenharmony_ci 350195972f6Sopenharmony_ci default: /* XXX Need code reject */ 351195972f6Sopenharmony_ci break; 352195972f6Sopenharmony_ci } 353195972f6Sopenharmony_ci} 354195972f6Sopenharmony_ci 355195972f6Sopenharmony_ci#if PPP_SERVER 356195972f6Sopenharmony_ci/* 357195972f6Sopenharmony_ci * upap_rauth - Receive Authenticate. 358195972f6Sopenharmony_ci */ 359195972f6Sopenharmony_cistatic void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) { 360195972f6Sopenharmony_ci u_char ruserlen, rpasswdlen; 361195972f6Sopenharmony_ci char *ruser; 362195972f6Sopenharmony_ci char *rpasswd; 363195972f6Sopenharmony_ci char rhostname[256]; 364195972f6Sopenharmony_ci int retcode; 365195972f6Sopenharmony_ci const char *msg; 366195972f6Sopenharmony_ci int msglen; 367195972f6Sopenharmony_ci 368195972f6Sopenharmony_ci if (pcb->upap.us_serverstate < UPAPSS_LISTEN) 369195972f6Sopenharmony_ci return; 370195972f6Sopenharmony_ci 371195972f6Sopenharmony_ci /* 372195972f6Sopenharmony_ci * If we receive a duplicate authenticate-request, we are 373195972f6Sopenharmony_ci * supposed to return the same status as for the first request. 374195972f6Sopenharmony_ci */ 375195972f6Sopenharmony_ci if (pcb->upap.us_serverstate == UPAPSS_OPEN) { 376195972f6Sopenharmony_ci upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ 377195972f6Sopenharmony_ci return; 378195972f6Sopenharmony_ci } 379195972f6Sopenharmony_ci if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) { 380195972f6Sopenharmony_ci upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ 381195972f6Sopenharmony_ci return; 382195972f6Sopenharmony_ci } 383195972f6Sopenharmony_ci 384195972f6Sopenharmony_ci /* 385195972f6Sopenharmony_ci * Parse user/passwd. 386195972f6Sopenharmony_ci */ 387195972f6Sopenharmony_ci if (len < 1) { 388195972f6Sopenharmony_ci UPAPDEBUG(("pap_rauth: rcvd short packet.")); 389195972f6Sopenharmony_ci return; 390195972f6Sopenharmony_ci } 391195972f6Sopenharmony_ci GETCHAR(ruserlen, inp); 392195972f6Sopenharmony_ci len -= sizeof (u_char) + ruserlen + sizeof (u_char); 393195972f6Sopenharmony_ci if (len < 0) { 394195972f6Sopenharmony_ci UPAPDEBUG(("pap_rauth: rcvd short packet.")); 395195972f6Sopenharmony_ci return; 396195972f6Sopenharmony_ci } 397195972f6Sopenharmony_ci ruser = (char *) inp; 398195972f6Sopenharmony_ci INCPTR(ruserlen, inp); 399195972f6Sopenharmony_ci GETCHAR(rpasswdlen, inp); 400195972f6Sopenharmony_ci if (len < rpasswdlen) { 401195972f6Sopenharmony_ci UPAPDEBUG(("pap_rauth: rcvd short packet.")); 402195972f6Sopenharmony_ci return; 403195972f6Sopenharmony_ci } 404195972f6Sopenharmony_ci 405195972f6Sopenharmony_ci rpasswd = (char *) inp; 406195972f6Sopenharmony_ci 407195972f6Sopenharmony_ci /* 408195972f6Sopenharmony_ci * Check the username and password given. 409195972f6Sopenharmony_ci */ 410195972f6Sopenharmony_ci retcode = UPAP_AUTHNAK; 411195972f6Sopenharmony_ci if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) { 412195972f6Sopenharmony_ci retcode = UPAP_AUTHACK; 413195972f6Sopenharmony_ci } 414195972f6Sopenharmony_ci BZERO(rpasswd, rpasswdlen); 415195972f6Sopenharmony_ci 416195972f6Sopenharmony_ci#if 0 /* UNUSED */ 417195972f6Sopenharmony_ci /* 418195972f6Sopenharmony_ci * Check remote number authorization. A plugin may have filled in 419195972f6Sopenharmony_ci * the remote number or added an allowed number, and rather than 420195972f6Sopenharmony_ci * return an authenticate failure, is leaving it for us to verify. 421195972f6Sopenharmony_ci */ 422195972f6Sopenharmony_ci if (retcode == UPAP_AUTHACK) { 423195972f6Sopenharmony_ci if (!auth_number()) { 424195972f6Sopenharmony_ci /* We do not want to leak info about the pap result. */ 425195972f6Sopenharmony_ci retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */ 426195972f6Sopenharmony_ci warn("calling number %q is not authorized", remote_number); 427195972f6Sopenharmony_ci } 428195972f6Sopenharmony_ci } 429195972f6Sopenharmony_ci 430195972f6Sopenharmony_ci msglen = strlen(msg); 431195972f6Sopenharmony_ci if (msglen > 255) 432195972f6Sopenharmony_ci msglen = 255; 433195972f6Sopenharmony_ci#endif /* UNUSED */ 434195972f6Sopenharmony_ci 435195972f6Sopenharmony_ci upap_sresp(pcb, retcode, id, msg, msglen); 436195972f6Sopenharmony_ci 437195972f6Sopenharmony_ci /* Null terminate and clean remote name. */ 438195972f6Sopenharmony_ci ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser); 439195972f6Sopenharmony_ci 440195972f6Sopenharmony_ci if (retcode == UPAP_AUTHACK) { 441195972f6Sopenharmony_ci pcb->upap.us_serverstate = UPAPSS_OPEN; 442195972f6Sopenharmony_ci ppp_notice("PAP peer authentication succeeded for %q", rhostname); 443195972f6Sopenharmony_ci auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen); 444195972f6Sopenharmony_ci } else { 445195972f6Sopenharmony_ci pcb->upap.us_serverstate = UPAPSS_BADAUTH; 446195972f6Sopenharmony_ci ppp_warn("PAP peer authentication failed for %q", rhostname); 447195972f6Sopenharmony_ci auth_peer_fail(pcb, PPP_PAP); 448195972f6Sopenharmony_ci } 449195972f6Sopenharmony_ci 450195972f6Sopenharmony_ci if (pcb->settings.pap_req_timeout > 0) 451195972f6Sopenharmony_ci UNTIMEOUT(upap_reqtimeout, pcb); 452195972f6Sopenharmony_ci} 453195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 454195972f6Sopenharmony_ci 455195972f6Sopenharmony_ci/* 456195972f6Sopenharmony_ci * upap_rauthack - Receive Authenticate-Ack. 457195972f6Sopenharmony_ci */ 458195972f6Sopenharmony_cistatic void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) { 459195972f6Sopenharmony_ci u_char msglen; 460195972f6Sopenharmony_ci char *msg; 461195972f6Sopenharmony_ci LWIP_UNUSED_ARG(id); 462195972f6Sopenharmony_ci 463195972f6Sopenharmony_ci if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ 464195972f6Sopenharmony_ci return; 465195972f6Sopenharmony_ci 466195972f6Sopenharmony_ci /* 467195972f6Sopenharmony_ci * Parse message. 468195972f6Sopenharmony_ci */ 469195972f6Sopenharmony_ci if (len < 1) { 470195972f6Sopenharmony_ci UPAPDEBUG(("pap_rauthack: ignoring missing msg-length.")); 471195972f6Sopenharmony_ci } else { 472195972f6Sopenharmony_ci GETCHAR(msglen, inp); 473195972f6Sopenharmony_ci if (msglen > 0) { 474195972f6Sopenharmony_ci len -= sizeof (u_char); 475195972f6Sopenharmony_ci if (len < msglen) { 476195972f6Sopenharmony_ci UPAPDEBUG(("pap_rauthack: rcvd short packet.")); 477195972f6Sopenharmony_ci return; 478195972f6Sopenharmony_ci } 479195972f6Sopenharmony_ci msg = (char *) inp; 480195972f6Sopenharmony_ci PRINTMSG(msg, msglen); 481195972f6Sopenharmony_ci } 482195972f6Sopenharmony_ci } 483195972f6Sopenharmony_ci 484195972f6Sopenharmony_ci pcb->upap.us_clientstate = UPAPCS_OPEN; 485195972f6Sopenharmony_ci 486195972f6Sopenharmony_ci auth_withpeer_success(pcb, PPP_PAP, 0); 487195972f6Sopenharmony_ci} 488195972f6Sopenharmony_ci 489195972f6Sopenharmony_ci 490195972f6Sopenharmony_ci/* 491195972f6Sopenharmony_ci * upap_rauthnak - Receive Authenticate-Nak. 492195972f6Sopenharmony_ci */ 493195972f6Sopenharmony_cistatic void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) { 494195972f6Sopenharmony_ci u_char msglen; 495195972f6Sopenharmony_ci char *msg; 496195972f6Sopenharmony_ci LWIP_UNUSED_ARG(id); 497195972f6Sopenharmony_ci 498195972f6Sopenharmony_ci if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ 499195972f6Sopenharmony_ci return; 500195972f6Sopenharmony_ci 501195972f6Sopenharmony_ci /* 502195972f6Sopenharmony_ci * Parse message. 503195972f6Sopenharmony_ci */ 504195972f6Sopenharmony_ci if (len < 1) { 505195972f6Sopenharmony_ci UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); 506195972f6Sopenharmony_ci } else { 507195972f6Sopenharmony_ci GETCHAR(msglen, inp); 508195972f6Sopenharmony_ci if (msglen > 0) { 509195972f6Sopenharmony_ci len -= sizeof (u_char); 510195972f6Sopenharmony_ci if (len < msglen) { 511195972f6Sopenharmony_ci UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); 512195972f6Sopenharmony_ci return; 513195972f6Sopenharmony_ci } 514195972f6Sopenharmony_ci msg = (char *) inp; 515195972f6Sopenharmony_ci PRINTMSG(msg, msglen); 516195972f6Sopenharmony_ci } 517195972f6Sopenharmony_ci } 518195972f6Sopenharmony_ci 519195972f6Sopenharmony_ci pcb->upap.us_clientstate = UPAPCS_BADAUTH; 520195972f6Sopenharmony_ci 521195972f6Sopenharmony_ci ppp_error("PAP authentication failed"); 522195972f6Sopenharmony_ci auth_withpeer_fail(pcb, PPP_PAP); 523195972f6Sopenharmony_ci} 524195972f6Sopenharmony_ci 525195972f6Sopenharmony_ci 526195972f6Sopenharmony_ci/* 527195972f6Sopenharmony_ci * upap_sauthreq - Send an Authenticate-Request. 528195972f6Sopenharmony_ci */ 529195972f6Sopenharmony_cistatic void upap_sauthreq(ppp_pcb *pcb) { 530195972f6Sopenharmony_ci struct pbuf *p; 531195972f6Sopenharmony_ci u_char *outp; 532195972f6Sopenharmony_ci int outlen; 533195972f6Sopenharmony_ci 534195972f6Sopenharmony_ci outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + 535195972f6Sopenharmony_ci pcb->upap.us_userlen + pcb->upap.us_passwdlen; 536195972f6Sopenharmony_ci p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); 537195972f6Sopenharmony_ci if(NULL == p) 538195972f6Sopenharmony_ci return; 539195972f6Sopenharmony_ci if(p->tot_len != p->len) { 540195972f6Sopenharmony_ci pbuf_free(p); 541195972f6Sopenharmony_ci return; 542195972f6Sopenharmony_ci } 543195972f6Sopenharmony_ci 544195972f6Sopenharmony_ci outp = (u_char*)p->payload; 545195972f6Sopenharmony_ci MAKEHEADER(outp, PPP_PAP); 546195972f6Sopenharmony_ci 547195972f6Sopenharmony_ci PUTCHAR(UPAP_AUTHREQ, outp); 548195972f6Sopenharmony_ci PUTCHAR(++pcb->upap.us_id, outp); 549195972f6Sopenharmony_ci PUTSHORT(outlen, outp); 550195972f6Sopenharmony_ci PUTCHAR(pcb->upap.us_userlen, outp); 551195972f6Sopenharmony_ci MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen); 552195972f6Sopenharmony_ci INCPTR(pcb->upap.us_userlen, outp); 553195972f6Sopenharmony_ci PUTCHAR(pcb->upap.us_passwdlen, outp); 554195972f6Sopenharmony_ci MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen); 555195972f6Sopenharmony_ci 556195972f6Sopenharmony_ci ppp_write(pcb, p); 557195972f6Sopenharmony_ci 558195972f6Sopenharmony_ci TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time); 559195972f6Sopenharmony_ci ++pcb->upap.us_transmits; 560195972f6Sopenharmony_ci pcb->upap.us_clientstate = UPAPCS_AUTHREQ; 561195972f6Sopenharmony_ci} 562195972f6Sopenharmony_ci 563195972f6Sopenharmony_ci#if PPP_SERVER 564195972f6Sopenharmony_ci/* 565195972f6Sopenharmony_ci * upap_sresp - Send a response (ack or nak). 566195972f6Sopenharmony_ci */ 567195972f6Sopenharmony_cistatic void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) { 568195972f6Sopenharmony_ci struct pbuf *p; 569195972f6Sopenharmony_ci u_char *outp; 570195972f6Sopenharmony_ci int outlen; 571195972f6Sopenharmony_ci 572195972f6Sopenharmony_ci outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; 573195972f6Sopenharmony_ci p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); 574195972f6Sopenharmony_ci if(NULL == p) 575195972f6Sopenharmony_ci return; 576195972f6Sopenharmony_ci if(p->tot_len != p->len) { 577195972f6Sopenharmony_ci pbuf_free(p); 578195972f6Sopenharmony_ci return; 579195972f6Sopenharmony_ci } 580195972f6Sopenharmony_ci 581195972f6Sopenharmony_ci outp = (u_char*)p->payload; 582195972f6Sopenharmony_ci MAKEHEADER(outp, PPP_PAP); 583195972f6Sopenharmony_ci 584195972f6Sopenharmony_ci PUTCHAR(code, outp); 585195972f6Sopenharmony_ci PUTCHAR(id, outp); 586195972f6Sopenharmony_ci PUTSHORT(outlen, outp); 587195972f6Sopenharmony_ci PUTCHAR(msglen, outp); 588195972f6Sopenharmony_ci MEMCPY(outp, msg, msglen); 589195972f6Sopenharmony_ci 590195972f6Sopenharmony_ci ppp_write(pcb, p); 591195972f6Sopenharmony_ci} 592195972f6Sopenharmony_ci#endif /* PPP_SERVER */ 593195972f6Sopenharmony_ci 594195972f6Sopenharmony_ci#if PRINTPKT_SUPPORT 595195972f6Sopenharmony_ci/* 596195972f6Sopenharmony_ci * upap_printpkt - print the contents of a PAP packet. 597195972f6Sopenharmony_ci */ 598195972f6Sopenharmony_cistatic const char* const upap_codenames[] = { 599195972f6Sopenharmony_ci "AuthReq", "AuthAck", "AuthNak" 600195972f6Sopenharmony_ci}; 601195972f6Sopenharmony_ci 602195972f6Sopenharmony_cistatic int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { 603195972f6Sopenharmony_ci int code, id, len; 604195972f6Sopenharmony_ci int mlen, ulen, wlen; 605195972f6Sopenharmony_ci const u_char *user, *pwd, *msg; 606195972f6Sopenharmony_ci const u_char *pstart; 607195972f6Sopenharmony_ci 608195972f6Sopenharmony_ci if (plen < UPAP_HEADERLEN) 609195972f6Sopenharmony_ci return 0; 610195972f6Sopenharmony_ci pstart = p; 611195972f6Sopenharmony_ci GETCHAR(code, p); 612195972f6Sopenharmony_ci GETCHAR(id, p); 613195972f6Sopenharmony_ci GETSHORT(len, p); 614195972f6Sopenharmony_ci if (len < UPAP_HEADERLEN || len > plen) 615195972f6Sopenharmony_ci return 0; 616195972f6Sopenharmony_ci 617195972f6Sopenharmony_ci if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames)) 618195972f6Sopenharmony_ci printer(arg, " %s", upap_codenames[code-1]); 619195972f6Sopenharmony_ci else 620195972f6Sopenharmony_ci printer(arg, " code=0x%x", code); 621195972f6Sopenharmony_ci printer(arg, " id=0x%x", id); 622195972f6Sopenharmony_ci len -= UPAP_HEADERLEN; 623195972f6Sopenharmony_ci switch (code) { 624195972f6Sopenharmony_ci case UPAP_AUTHREQ: 625195972f6Sopenharmony_ci if (len < 1) 626195972f6Sopenharmony_ci break; 627195972f6Sopenharmony_ci ulen = p[0]; 628195972f6Sopenharmony_ci if (len < ulen + 2) 629195972f6Sopenharmony_ci break; 630195972f6Sopenharmony_ci wlen = p[ulen + 1]; 631195972f6Sopenharmony_ci if (len < ulen + wlen + 2) 632195972f6Sopenharmony_ci break; 633195972f6Sopenharmony_ci user = (const u_char *) (p + 1); 634195972f6Sopenharmony_ci pwd = (const u_char *) (p + ulen + 2); 635195972f6Sopenharmony_ci p += ulen + wlen + 2; 636195972f6Sopenharmony_ci len -= ulen + wlen + 2; 637195972f6Sopenharmony_ci printer(arg, " user="); 638195972f6Sopenharmony_ci ppp_print_string(user, ulen, printer, arg); 639195972f6Sopenharmony_ci printer(arg, " password="); 640195972f6Sopenharmony_ci/* FIXME: require ppp_pcb struct as printpkt() argument */ 641195972f6Sopenharmony_ci#if 0 642195972f6Sopenharmony_ci if (!pcb->settings.hide_password) 643195972f6Sopenharmony_ci#endif 644195972f6Sopenharmony_ci ppp_print_string(pwd, wlen, printer, arg); 645195972f6Sopenharmony_ci#if 0 646195972f6Sopenharmony_ci else 647195972f6Sopenharmony_ci printer(arg, "<hidden>"); 648195972f6Sopenharmony_ci#endif 649195972f6Sopenharmony_ci break; 650195972f6Sopenharmony_ci case UPAP_AUTHACK: 651195972f6Sopenharmony_ci case UPAP_AUTHNAK: 652195972f6Sopenharmony_ci if (len < 1) 653195972f6Sopenharmony_ci break; 654195972f6Sopenharmony_ci mlen = p[0]; 655195972f6Sopenharmony_ci if (len < mlen + 1) 656195972f6Sopenharmony_ci break; 657195972f6Sopenharmony_ci msg = (const u_char *) (p + 1); 658195972f6Sopenharmony_ci p += mlen + 1; 659195972f6Sopenharmony_ci len -= mlen + 1; 660195972f6Sopenharmony_ci printer(arg, " "); 661195972f6Sopenharmony_ci ppp_print_string(msg, mlen, printer, arg); 662195972f6Sopenharmony_ci break; 663195972f6Sopenharmony_ci default: 664195972f6Sopenharmony_ci break; 665195972f6Sopenharmony_ci } 666195972f6Sopenharmony_ci 667195972f6Sopenharmony_ci /* print the rest of the bytes in the packet */ 668195972f6Sopenharmony_ci for (; len > 0; --len) { 669195972f6Sopenharmony_ci GETCHAR(code, p); 670195972f6Sopenharmony_ci printer(arg, " %.2x", code); 671195972f6Sopenharmony_ci } 672195972f6Sopenharmony_ci 673195972f6Sopenharmony_ci return p - pstart; 674195972f6Sopenharmony_ci} 675195972f6Sopenharmony_ci#endif /* PRINTPKT_SUPPORT */ 676195972f6Sopenharmony_ci 677195972f6Sopenharmony_ci#endif /* PPP_SUPPORT && PAP_SUPPORT */ 678