pap.c revision 134789
136270Swpaul/*- 236270Swpaul * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 336270Swpaul * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 436270Swpaul * Internet Initiative Japan, Inc (IIJ) 536270Swpaul * All rights reserved. 636270Swpaul * 736270Swpaul * Redistribution and use in source and binary forms, with or without 836270Swpaul * modification, are permitted provided that the following conditions 936270Swpaul * are met: 1036270Swpaul * 1. Redistributions of source code must retain the above copyright 1136270Swpaul * notice, this list of conditions and the following disclaimer. 1236270Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1336270Swpaul * notice, this list of conditions and the following disclaimer in the 1436270Swpaul * documentation and/or other materials provided with the distribution. 1536270Swpaul * 1636270Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1736270Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1836270Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1936270Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2036270Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2136270Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2236270Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2336270Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2436270Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2536270Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2636270Swpaul * SUCH DAMAGE. 2736270Swpaul * 2836270Swpaul * $FreeBSD: head/usr.sbin/ppp/pap.c 134789 2004-09-05 01:46:52Z brian $ 2936270Swpaul */ 3036270Swpaul 3136270Swpaul#include <sys/param.h> 3243235Swpaul#include <netinet/in.h> 3336270Swpaul#include <netinet/in_systm.h> 3436270Swpaul#include <netinet/ip.h> 3536270Swpaul#include <sys/socket.h> 3636270Swpaul#include <sys/un.h> 3736270Swpaul 3836270Swpaul#include <stdlib.h> 3936270Swpaul#include <string.h> /* strlen/memcpy */ 4036270Swpaul#include <termios.h> 4139583Swpaul 4236270Swpaul#include "layer.h" 4336270Swpaul#include "mbuf.h" 4436270Swpaul#include "log.h" 4536270Swpaul#include "defs.h" 4639583Swpaul#include "timer.h" 4736270Swpaul#include "fsm.h" 4836270Swpaul#include "auth.h" 4936270Swpaul#include "pap.h" 5036270Swpaul#include "lqr.h" 5136270Swpaul#include "hdlc.h" 5236270Swpaul#include "lcp.h" 5336270Swpaul#include "proto.h" 5436270Swpaul#include "async.h" 5536270Swpaul#include "throughput.h" 5636270Swpaul#include "ccp.h" 5736270Swpaul#include "link.h" 5839583Swpaul#include "descriptor.h" 5936270Swpaul#include "physical.h" 6036270Swpaul#include "iplist.h" 6136270Swpaul#include "slcompress.h" 6236270Swpaul#include "ncpaddr.h" 6336270Swpaul#include "ipcp.h" 6436270Swpaul#include "filter.h" 6536270Swpaul#include "mp.h" 6639583Swpaul#ifndef NORADIUS 6739583Swpaul#include "radius.h" 6839583Swpaul#endif 6939583Swpaul#include "ipv6cp.h" 7039583Swpaul#include "ncp.h" 7139583Swpaul#include "bundle.h" 7239583Swpaul#include "chat.h" 7339583Swpaul#include "chap.h" 7439583Swpaul#include "cbcp.h" 7536270Swpaul#include "datalink.h" 7636270Swpaul 7739583Swpaulstatic const char * const papcodes[] = { 7836270Swpaul "???", "REQUEST", "SUCCESS", "FAILURE" 7936270Swpaul}; 8036270Swpaul#define MAXPAPCODE (sizeof papcodes / sizeof papcodes[0] - 1) 8136270Swpaul 8236270Swpaulstatic void 8336270Swpaulpap_Req(struct authinfo *authp) 8436270Swpaul{ 8536270Swpaul struct bundle *bundle = authp->physical->dl->bundle; 8636270Swpaul struct fsmheader lh; 8736270Swpaul struct mbuf *bp; 8836270Swpaul u_char *cp; 8936270Swpaul int namelen, keylen, plen; 9036270Swpaul 9136270Swpaul namelen = strlen(bundle->cfg.auth.name); 9236270Swpaul keylen = strlen(bundle->cfg.auth.key); 9336270Swpaul plen = namelen + keylen + 2; 9436270Swpaul log_Printf(LogDEBUG, "pap_Req: namelen = %d, keylen = %d\n", namelen, keylen); 9536270Swpaul log_Printf(LogPHASE, "Pap Output: %s ********\n", bundle->cfg.auth.name); 9636270Swpaul if (*bundle->cfg.auth.name == '\0') 9736270Swpaul log_Printf(LogWARN, "Sending empty PAP authname!\n"); 9836270Swpaul lh.code = PAP_REQUEST; 9936270Swpaul lh.id = authp->id; 10036270Swpaul lh.length = htons(plen + sizeof(struct fsmheader)); 10136270Swpaul bp = m_get(plen + sizeof(struct fsmheader), MB_PAPOUT); 10236270Swpaul memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 10336270Swpaul cp = MBUF_CTOP(bp) + sizeof(struct fsmheader); 10436270Swpaul *cp++ = namelen; 10536270Swpaul memcpy(cp, bundle->cfg.auth.name, namelen); 10636270Swpaul cp += namelen; 10736270Swpaul *cp++ = keylen; 10836270Swpaul memcpy(cp, bundle->cfg.auth.key, keylen); 10936270Swpaul link_PushPacket(&authp->physical->link, bp, bundle, 11036270Swpaul LINK_QUEUES(&authp->physical->link) - 1, PROTO_PAP); 11136270Swpaul} 11236270Swpaul 11336270Swpaulstatic void 11436270SwpaulSendPapCode(struct authinfo *authp, int code, const char *message) 11536270Swpaul{ 11636270Swpaul struct fsmheader lh; 11736270Swpaul struct mbuf *bp; 11836270Swpaul u_char *cp; 11936270Swpaul int plen, mlen; 12036270Swpaul 12136270Swpaul lh.code = code; 12236270Swpaul lh.id = authp->id; 12336270Swpaul mlen = strlen(message); 12436270Swpaul plen = mlen + 1; 12536270Swpaul lh.length = htons(plen + sizeof(struct fsmheader)); 12636270Swpaul bp = m_get(plen + sizeof(struct fsmheader), MB_PAPOUT); 12736270Swpaul memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 12836270Swpaul cp = MBUF_CTOP(bp) + sizeof(struct fsmheader); 12936270Swpaul /* 13036270Swpaul * If our message is longer than 255 bytes, truncate the length to 13136270Swpaul * 255 and send the entire message anyway. Maybe the other end will 13236270Swpaul * display it... (see pap_Input() !) 13336270Swpaul */ 13436270Swpaul *cp++ = mlen > 255 ? 255 : mlen; 13536270Swpaul memcpy(cp, message, mlen); 13636270Swpaul log_Printf(LogPHASE, "Pap Output: %s\n", papcodes[code]); 13736270Swpaul 13836270Swpaul link_PushPacket(&authp->physical->link, bp, authp->physical->dl->bundle, 13936270Swpaul LINK_QUEUES(&authp->physical->link) - 1, PROTO_PAP); 14036270Swpaul} 14136270Swpaul 14236270Swpaulstatic void 14336270Swpaulpap_Success(struct authinfo *authp) 14436270Swpaul{ 14536270Swpaul struct bundle *bundle = authp->physical->dl->bundle; 14636270Swpaul 14736270Swpaul datalink_GotAuthname(authp->physical->dl, authp->in.name); 14836270Swpaul#ifndef NORADIUS 14936270Swpaul if (*bundle->radius.cfg.file && bundle->radius.repstr) 15036270Swpaul SendPapCode(authp, PAP_ACK, bundle->radius.repstr); 15136270Swpaul else 15236270Swpaul#endif 15336270Swpaul SendPapCode(authp, PAP_ACK, "Greetings!!"); 15436270Swpaul authp->physical->link.lcp.auth_ineed = 0; 15536270Swpaul if (Enabled(bundle, OPT_UTMP)) 15636270Swpaul physical_Login(authp->physical, authp->in.name); 15736270Swpaul 15836270Swpaul if (authp->physical->link.lcp.auth_iwait == 0) 15936270Swpaul /* 16036270Swpaul * Either I didn't need to authenticate, or I've already been 16136270Swpaul * told that I got the answer right. 16236270Swpaul */ 16336270Swpaul datalink_AuthOk(authp->physical->dl); 16436270Swpaul} 16536270Swpaul 16636270Swpaulstatic void 16736270Swpaulpap_Failure(struct authinfo *authp) 16836270Swpaul{ 16936270Swpaul SendPapCode(authp, PAP_NAK, "Login incorrect"); 17036270Swpaul datalink_AuthNotOk(authp->physical->dl); 17136270Swpaul} 17236270Swpaul 17336270Swpaulvoid 17436270Swpaulpap_Init(struct authinfo *pap, struct physical *p) 17536270Swpaul{ 17636270Swpaul auth_Init(pap, p, pap_Req, pap_Success, pap_Failure); 17736270Swpaul} 17836270Swpaul 17936270Swpaulstruct mbuf * 18036270Swpaulpap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 18136270Swpaul{ 18236270Swpaul struct physical *p = link2physical(l); 18336270Swpaul struct authinfo *authp = &p->dl->pap; 18436270Swpaul u_char nlen, klen, *key; 18536270Swpaul const char *txt; 18636270Swpaul int txtlen; 18736270Swpaul 18836270Swpaul if (p == NULL) { 18936270Swpaul log_Printf(LogERROR, "pap_Input: Not a physical link - dropped\n"); 19036270Swpaul m_freem(bp); 19136270Swpaul return NULL; 19236270Swpaul } 19336270Swpaul 19436270Swpaul if (bundle_Phase(bundle) != PHASE_NETWORK && 19536270Swpaul bundle_Phase(bundle) != PHASE_AUTHENTICATE) { 19636270Swpaul log_Printf(LogPHASE, "Unexpected pap input - dropped !\n"); 19736270Swpaul m_freem(bp); 19836270Swpaul return NULL; 19936270Swpaul } 20036270Swpaul 20136270Swpaul if ((bp = auth_ReadHeader(authp, bp)) == NULL && 20236270Swpaul ntohs(authp->in.hdr.length) == 0) { 20336270Swpaul log_Printf(LogWARN, "Pap Input: Truncated header !\n"); 20436270Swpaul return NULL; 20536270Swpaul } 20636270Swpaul 20736270Swpaul if (authp->in.hdr.code == 0 || authp->in.hdr.code > MAXPAPCODE) { 20839957Swpaul log_Printf(LogPHASE, "Pap Input: %d: Bad PAP code !\n", authp->in.hdr.code); 20939957Swpaul m_freem(bp); 21039957Swpaul return NULL; 21139957Swpaul } 21239957Swpaul 21339957Swpaul if (authp->in.hdr.code != PAP_REQUEST && authp->id != authp->in.hdr.id && 21439957Swpaul Enabled(bundle, OPT_IDCHECK)) { 21539583Swpaul /* Wrong conversation dude ! */ 21639583Swpaul log_Printf(LogPHASE, "Pap Input: %s dropped (got id %d, not %d)\n", 21736270Swpaul papcodes[authp->in.hdr.code], authp->in.hdr.id, authp->id); 21836270Swpaul m_freem(bp); 21941591Sarchie return NULL; 22041591Sarchie } 22143235Swpaul m_settype(bp, MB_PAPIN); 22236270Swpaul authp->id = authp->in.hdr.id; /* We respond with this id */ 22336270Swpaul 22439583Swpaul if (bp) { 22539583Swpaul bp = mbuf_Read(bp, &nlen, 1); 22639583Swpaul if (authp->in.hdr.code == PAP_ACK) { 22739583Swpaul /* 22839583Swpaul * Don't restrict the length of our acknowledgement freetext to 22939583Swpaul * nlen (a one-byte length). Show the rest of the ack packet 23039583Swpaul * instead. This isn't really part of the protocol..... 23139583Swpaul */ 23239583Swpaul bp = m_pullup(bp); 23339583Swpaul txt = MBUF_CTOP(bp); 23439583Swpaul txtlen = m_length(bp); 23539583Swpaul } else { 23639583Swpaul bp = auth_ReadName(authp, bp, nlen); 23739583Swpaul txt = authp->in.name; 23839583Swpaul txtlen = strlen(authp->in.name); 23939583Swpaul } 24039583Swpaul } else { 24139583Swpaul txt = ""; 24239583Swpaul txtlen = 0; 24339583Swpaul } 24439583Swpaul 24539583Swpaul log_Printf(LogPHASE, "Pap Input: %s (%.*s)\n", 24639583Swpaul papcodes[authp->in.hdr.code], txtlen, txt); 24739583Swpaul 24839583Swpaul switch (authp->in.hdr.code) { 24939583Swpaul case PAP_REQUEST: 25039583Swpaul if (bp == NULL) { 25139583Swpaul log_Printf(LogPHASE, "Pap Input: No key given !\n"); 25239583Swpaul break; 25339583Swpaul } 25439583Swpaul bp = mbuf_Read(bp, &klen, 1); 25539583Swpaul if (m_length(bp) < klen) { 25639583Swpaul log_Printf(LogERROR, "Pap Input: Truncated key !\n"); 25739583Swpaul break; 25839583Swpaul } 25939583Swpaul if ((key = malloc(klen+1)) == NULL) { 26039583Swpaul log_Printf(LogERROR, "Pap Input: Out of memory !\n"); 26139583Swpaul break; 26239583Swpaul } 26339583Swpaul bp = mbuf_Read(bp, key, klen); 26439583Swpaul key[klen] = '\0'; 26536270Swpaul 26636270Swpaul#ifndef NORADIUS 26736270Swpaul if (*bundle->radius.cfg.file) { 26836270Swpaul if (!radius_Authenticate(&bundle->radius, authp, authp->in.name, 26936270Swpaul key, strlen(key), NULL, 0)) 27036270Swpaul pap_Failure(authp); 27136270Swpaul } else 27236270Swpaul#endif 27336270Swpaul if (auth_Validate(bundle, authp->in.name, key)) 27436270Swpaul pap_Success(authp); 27536270Swpaul else 27636270Swpaul pap_Failure(authp); 27736270Swpaul 27836270Swpaul free(key); 27936270Swpaul break; 28036270Swpaul 28136270Swpaul case PAP_ACK: 28236270Swpaul auth_StopTimer(authp); 28336270Swpaul if (p->link.lcp.auth_iwait == PROTO_PAP) { 28436270Swpaul p->link.lcp.auth_iwait = 0; 28536270Swpaul if (p->link.lcp.auth_ineed == 0) 28637626Swpaul /* 28737626Swpaul * We've succeeded in our ``login'' 28837626Swpaul * If we're not expecting the peer to authenticate (or he already 28937626Swpaul * has), proceed to network phase. 29037626Swpaul */ 29137626Swpaul datalink_AuthOk(p->dl); 29237626Swpaul } 29337626Swpaul break; 29437626Swpaul 29537626Swpaul case PAP_NAK: 29637626Swpaul auth_StopTimer(authp); 29737626Swpaul datalink_AuthNotOk(p->dl); 29836270Swpaul break; 29936270Swpaul } 30036270Swpaul 30136270Swpaul m_freem(bp); 30236270Swpaul return NULL; 30336270Swpaul} 30436270Swpaul