178189Sbrian/*- 278189Sbrian * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 378189Sbrian * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 478189Sbrian * Internet Initiative Japan, Inc (IIJ) 578189Sbrian * All rights reserved. 66059Samurai * 778189Sbrian * Redistribution and use in source and binary forms, with or without 878189Sbrian * modification, are permitted provided that the following conditions 978189Sbrian * are met: 1078189Sbrian * 1. Redistributions of source code must retain the above copyright 1178189Sbrian * notice, this list of conditions and the following disclaimer. 1278189Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1378189Sbrian * notice, this list of conditions and the following disclaimer in the 1478189Sbrian * documentation and/or other materials provided with the distribution. 156059Samurai * 1678189Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1778189Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1878189Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1978189Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2078189Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2178189Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2278189Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2378189Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2478189Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2578189Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2678189Sbrian * SUCH DAMAGE. 276059Samurai * 2850479Speter * $FreeBSD$ 296059Samurai */ 3078189Sbrian 3143313Sbrian#include <sys/param.h> 3230715Sbrian#include <netinet/in.h> 3336285Sbrian#include <netinet/in_systm.h> 3436285Sbrian#include <netinet/ip.h> 3581634Sbrian#include <sys/socket.h> 3636285Sbrian#include <sys/un.h> 3730715Sbrian 3843693Sbrian#include <stdlib.h> 3949472Sbrian#include <string.h> /* strlen/memcpy */ 4036285Sbrian#include <termios.h> 4130715Sbrian 4246686Sbrian#include "layer.h" 4330715Sbrian#include "mbuf.h" 4430715Sbrian#include "log.h" 4530715Sbrian#include "defs.h" 4630715Sbrian#include "timer.h" 476059Samurai#include "fsm.h" 4836285Sbrian#include "auth.h" 496059Samurai#include "pap.h" 5036285Sbrian#include "lqr.h" 516059Samurai#include "hdlc.h" 5263484Sbrian#include "lcp.h" 5346686Sbrian#include "proto.h" 5436285Sbrian#include "async.h" 5536285Sbrian#include "throughput.h" 5636285Sbrian#include "ccp.h" 5736285Sbrian#include "link.h" 5836285Sbrian#include "descriptor.h" 5936285Sbrian#include "physical.h" 6036285Sbrian#include "iplist.h" 6136285Sbrian#include "slcompress.h" 6281634Sbrian#include "ncpaddr.h" 6336285Sbrian#include "ipcp.h" 6436285Sbrian#include "filter.h" 6536285Sbrian#include "mp.h" 6643313Sbrian#ifndef NORADIUS 6743313Sbrian#include "radius.h" 6843313Sbrian#endif 6981634Sbrian#include "ipv6cp.h" 7081634Sbrian#include "ncp.h" 7136285Sbrian#include "bundle.h" 7236285Sbrian#include "chat.h" 7336285Sbrian#include "chap.h" 7438174Sbrian#include "cbcp.h" 7536285Sbrian#include "datalink.h" 766059Samurai 7755146Sbrianstatic const char * const papcodes[] = { 7855146Sbrian "???", "REQUEST", "SUCCESS", "FAILURE" 7955146Sbrian}; 8043693Sbrian#define MAXPAPCODE (sizeof papcodes / sizeof papcodes[0] - 1) 816059Samurai 8243693Sbrianstatic void 8343693Sbrianpap_Req(struct authinfo *authp) 846059Samurai{ 8543693Sbrian struct bundle *bundle = authp->physical->dl->bundle; 866059Samurai struct fsmheader lh; 876059Samurai struct mbuf *bp; 886059Samurai u_char *cp; 896059Samurai int namelen, keylen, plen; 906059Samurai 9143693Sbrian namelen = strlen(bundle->cfg.auth.name); 9243693Sbrian keylen = strlen(bundle->cfg.auth.key); 936059Samurai plen = namelen + keylen + 2; 9443693Sbrian log_Printf(LogDEBUG, "pap_Req: namelen = %d, keylen = %d\n", namelen, keylen); 9543693Sbrian log_Printf(LogPHASE, "Pap Output: %s ********\n", bundle->cfg.auth.name); 9643693Sbrian if (*bundle->cfg.auth.name == '\0') 9737926Sbrian log_Printf(LogWARN, "Sending empty PAP authname!\n"); 986059Samurai lh.code = PAP_REQUEST; 9943693Sbrian lh.id = authp->id; 1006059Samurai lh.length = htons(plen + sizeof(struct fsmheader)); 10154912Sbrian bp = m_get(plen + sizeof(struct fsmheader), MB_PAPOUT); 10230715Sbrian memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 1036059Samurai cp = MBUF_CTOP(bp) + sizeof(struct fsmheader); 1046059Samurai *cp++ = namelen; 10543693Sbrian memcpy(cp, bundle->cfg.auth.name, namelen); 1066059Samurai cp += namelen; 1076059Samurai *cp++ = keylen; 10843693Sbrian memcpy(cp, bundle->cfg.auth.key, keylen); 10950867Sbrian link_PushPacket(&authp->physical->link, bp, bundle, 11050867Sbrian LINK_QUEUES(&authp->physical->link) - 1, PROTO_PAP); 1116059Samurai} 1126059Samurai 1136059Samuraistatic void 11443693SbrianSendPapCode(struct authinfo *authp, int code, const char *message) 1156059Samurai{ 1166059Samurai struct fsmheader lh; 1176059Samurai struct mbuf *bp; 1186059Samurai u_char *cp; 1196059Samurai int plen, mlen; 1206059Samurai 1216059Samurai lh.code = code; 12243693Sbrian lh.id = authp->id; 1236059Samurai mlen = strlen(message); 1246059Samurai plen = mlen + 1; 1256059Samurai lh.length = htons(plen + sizeof(struct fsmheader)); 12654912Sbrian bp = m_get(plen + sizeof(struct fsmheader), MB_PAPOUT); 12730715Sbrian memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 1286059Samurai cp = MBUF_CTOP(bp) + sizeof(struct fsmheader); 12953734Sbrian /* 13053734Sbrian * If our message is longer than 255 bytes, truncate the length to 13153734Sbrian * 255 and send the entire message anyway. Maybe the other end will 13253734Sbrian * display it... (see pap_Input() !) 13353734Sbrian */ 13453734Sbrian *cp++ = mlen > 255 ? 255 : mlen; 13530715Sbrian memcpy(cp, message, mlen); 13637926Sbrian log_Printf(LogPHASE, "Pap Output: %s\n", papcodes[code]); 13743693Sbrian 13846686Sbrian link_PushPacket(&authp->physical->link, bp, authp->physical->dl->bundle, 13950867Sbrian LINK_QUEUES(&authp->physical->link) - 1, PROTO_PAP); 1406059Samurai} 1416059Samurai 14243693Sbrianstatic void 14343693Sbrianpap_Success(struct authinfo *authp) 1446059Samurai{ 14596324Sbrian struct bundle *bundle = authp->physical->dl->bundle; 14696324Sbrian 14743693Sbrian datalink_GotAuthname(authp->physical->dl, authp->in.name); 14896324Sbrian#ifndef NORADIUS 14996324Sbrian if (*bundle->radius.cfg.file && bundle->radius.repstr) 15096324Sbrian SendPapCode(authp, PAP_ACK, bundle->radius.repstr); 15196324Sbrian else 15296324Sbrian#endif 15396324Sbrian SendPapCode(authp, PAP_ACK, "Greetings!!"); 15443693Sbrian authp->physical->link.lcp.auth_ineed = 0; 15596324Sbrian if (Enabled(bundle, OPT_UTMP)) 15643693Sbrian physical_Login(authp->physical, authp->in.name); 1576059Samurai 15843693Sbrian if (authp->physical->link.lcp.auth_iwait == 0) 15943693Sbrian /* 16043693Sbrian * Either I didn't need to authenticate, or I've already been 16143693Sbrian * told that I got the answer right. 16243693Sbrian */ 16343693Sbrian datalink_AuthOk(authp->physical->dl); 16443693Sbrian} 16518752Sjkh 16643693Sbrianstatic void 16743693Sbrianpap_Failure(struct authinfo *authp) 16843693Sbrian{ 16943693Sbrian SendPapCode(authp, PAP_NAK, "Login incorrect"); 17043693Sbrian datalink_AuthNotOk(authp->physical->dl); 1716059Samurai} 1726059Samurai 1736059Samuraivoid 17443693Sbrianpap_Init(struct authinfo *pap, struct physical *p) 1756059Samurai{ 17643693Sbrian auth_Init(pap, p, pap_Req, pap_Success, pap_Failure); 17743693Sbrian} 1786059Samurai 17946686Sbrianstruct mbuf * 18046686Sbrianpap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 18143693Sbrian{ 18246686Sbrian struct physical *p = link2physical(l); 18343693Sbrian struct authinfo *authp = &p->dl->pap; 18443693Sbrian u_char nlen, klen, *key; 18553734Sbrian const char *txt; 18653734Sbrian int txtlen; 18736285Sbrian 18846686Sbrian if (p == NULL) { 18946686Sbrian log_Printf(LogERROR, "pap_Input: Not a physical link - dropped\n"); 19054912Sbrian m_freem(bp); 19146686Sbrian return NULL; 19246686Sbrian } 19346686Sbrian 19446686Sbrian if (bundle_Phase(bundle) != PHASE_NETWORK && 19546686Sbrian bundle_Phase(bundle) != PHASE_AUTHENTICATE) { 19645220Sbrian log_Printf(LogPHASE, "Unexpected pap input - dropped !\n"); 19754912Sbrian m_freem(bp); 19846686Sbrian return NULL; 19945220Sbrian } 20045220Sbrian 20144159Sbrian if ((bp = auth_ReadHeader(authp, bp)) == NULL && 20244159Sbrian ntohs(authp->in.hdr.length) == 0) { 20344159Sbrian log_Printf(LogWARN, "Pap Input: Truncated header !\n"); 20446686Sbrian return NULL; 20544159Sbrian } 20643693Sbrian 20743693Sbrian if (authp->in.hdr.code == 0 || authp->in.hdr.code > MAXPAPCODE) { 20843693Sbrian log_Printf(LogPHASE, "Pap Input: %d: Bad PAP code !\n", authp->in.hdr.code); 20954912Sbrian m_freem(bp); 21046686Sbrian return NULL; 21143693Sbrian } 21243693Sbrian 21343693Sbrian if (authp->in.hdr.code != PAP_REQUEST && authp->id != authp->in.hdr.id && 21446686Sbrian Enabled(bundle, OPT_IDCHECK)) { 21543693Sbrian /* Wrong conversation dude ! */ 21643693Sbrian log_Printf(LogPHASE, "Pap Input: %s dropped (got id %d, not %d)\n", 21743693Sbrian papcodes[authp->in.hdr.code], authp->in.hdr.id, authp->id); 21854912Sbrian m_freem(bp); 21946686Sbrian return NULL; 22043693Sbrian } 22154912Sbrian m_settype(bp, MB_PAPIN); 22243693Sbrian authp->id = authp->in.hdr.id; /* We respond with this id */ 22343693Sbrian 22443693Sbrian if (bp) { 22543693Sbrian bp = mbuf_Read(bp, &nlen, 1); 22653734Sbrian if (authp->in.hdr.code == PAP_ACK) { 22753734Sbrian /* 22853734Sbrian * Don't restrict the length of our acknowledgement freetext to 22953734Sbrian * nlen (a one-byte length). Show the rest of the ack packet 23053734Sbrian * instead. This isn't really part of the protocol..... 23153734Sbrian */ 23254912Sbrian bp = m_pullup(bp); 23353734Sbrian txt = MBUF_CTOP(bp); 23454912Sbrian txtlen = m_length(bp); 23553734Sbrian } else { 23653734Sbrian bp = auth_ReadName(authp, bp, nlen); 23753734Sbrian txt = authp->in.name; 23853734Sbrian txtlen = strlen(authp->in.name); 23953734Sbrian } 24053734Sbrian } else { 24153734Sbrian txt = ""; 24253734Sbrian txtlen = 0; 24343693Sbrian } 24443693Sbrian 24553734Sbrian log_Printf(LogPHASE, "Pap Input: %s (%.*s)\n", 24653734Sbrian papcodes[authp->in.hdr.code], txtlen, txt); 24743693Sbrian 24843693Sbrian switch (authp->in.hdr.code) { 24943693Sbrian case PAP_REQUEST: 25043693Sbrian if (bp == NULL) { 25143693Sbrian log_Printf(LogPHASE, "Pap Input: No key given !\n"); 25243693Sbrian break; 2536059Samurai } 25443693Sbrian bp = mbuf_Read(bp, &klen, 1); 25554912Sbrian if (m_length(bp) < klen) { 25643693Sbrian log_Printf(LogERROR, "Pap Input: Truncated key !\n"); 25743693Sbrian break; 25843693Sbrian } 25943693Sbrian if ((key = malloc(klen+1)) == NULL) { 26043693Sbrian log_Printf(LogERROR, "Pap Input: Out of memory !\n"); 26143693Sbrian break; 26243693Sbrian } 26343693Sbrian bp = mbuf_Read(bp, key, klen); 26443693Sbrian key[klen] = '\0'; 26543693Sbrian 26643693Sbrian#ifndef NORADIUS 26796730Sbrian if (*bundle->radius.cfg.file) { 26896730Sbrian if (!radius_Authenticate(&bundle->radius, authp, authp->in.name, 26998311Sbrian key, strlen(key), NULL, 0)) 27096730Sbrian pap_Failure(authp); 27196730Sbrian } else 27243693Sbrian#endif 273134789Sbrian if (auth_Validate(bundle, authp->in.name, key)) 27443693Sbrian pap_Success(authp); 27543693Sbrian else 27643693Sbrian pap_Failure(authp); 27743693Sbrian 27843693Sbrian free(key); 27943693Sbrian break; 28043693Sbrian 28143693Sbrian case PAP_ACK: 28243693Sbrian auth_StopTimer(authp); 28343693Sbrian if (p->link.lcp.auth_iwait == PROTO_PAP) { 28443693Sbrian p->link.lcp.auth_iwait = 0; 28543693Sbrian if (p->link.lcp.auth_ineed == 0) 28643693Sbrian /* 28743693Sbrian * We've succeeded in our ``login'' 28843693Sbrian * If we're not expecting the peer to authenticate (or he already 28943693Sbrian * has), proceed to network phase. 29043693Sbrian */ 29143693Sbrian datalink_AuthOk(p->dl); 29243693Sbrian } 29343693Sbrian break; 29443693Sbrian 29543693Sbrian case PAP_NAK: 29643693Sbrian auth_StopTimer(authp); 29743693Sbrian datalink_AuthNotOk(p->dl); 29843693Sbrian break; 2996059Samurai } 30043693Sbrian 30154912Sbrian m_freem(bp); 30246686Sbrian return NULL; 3036059Samurai} 304