1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * PPP Secret Key Module 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan, Inc. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 2097d92980SPeter Wemm * $FreeBSD$ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23c3899f8dSAtsushi Murai * o Implement check against with registered IP addresses. 24af57ed9fSAtsushi Murai */ 25972a1bcfSBrian Somers #include <sys/param.h> 2675240ed1SBrian Somers #include <netinet/in.h> 27eaa4df37SBrian Somers #include <netinet/in_systm.h> 28eaa4df37SBrian Somers #include <netinet/ip.h> 291fa665f5SBrian Somers #include <sys/un.h> 3075240ed1SBrian Somers 31d5015272SBrian Somers #include <pwd.h> 3275240ed1SBrian Somers #include <stdio.h> 3375240ed1SBrian Somers #include <string.h> 34aceaed92SBrian Somers #include <termios.h> 3575240ed1SBrian Somers #include <unistd.h> 3675240ed1SBrian Somers 375d9e6103SBrian Somers #include "layer.h" 3875240ed1SBrian Somers #include "mbuf.h" 3975240ed1SBrian Somers #include "defs.h" 40aceaed92SBrian Somers #include "log.h" 4175240ed1SBrian Somers #include "timer.h" 42af57ed9fSAtsushi Murai #include "fsm.h" 4329e275ceSBrian Somers #include "iplist.h" 4429e275ceSBrian Somers #include "throughput.h" 45eaa4df37SBrian Somers #include "slcompress.h" 465a72b6edSBrian Somers #include "lqr.h" 475a72b6edSBrian Somers #include "hdlc.h" 48af57ed9fSAtsushi Murai #include "ipcp.h" 4953c9f6c0SAtsushi Murai #include "auth.h" 5075240ed1SBrian Somers #include "systems.h" 516140ba11SBrian Somers #include "lcp.h" 523b0f8d2eSBrian Somers #include "ccp.h" 536140ba11SBrian Somers #include "link.h" 5442d4d396SBrian Somers #include "descriptor.h" 55b6dec9f0SBrian Somers #include "chat.h" 565d9e6103SBrian Somers #include "proto.h" 575ca5389aSBrian Somers #include "filter.h" 583b0f8d2eSBrian Somers #include "mp.h" 59972a1bcfSBrian Somers #ifndef NORADIUS 60972a1bcfSBrian Somers #include "radius.h" 61972a1bcfSBrian Somers #endif 62aceaed92SBrian Somers #include "cbcp.h" 63aceaed92SBrian Somers #include "chap.h" 64aceaed92SBrian Somers #include "async.h" 65aceaed92SBrian Somers #include "physical.h" 66aceaed92SBrian Somers #include "datalink.h" 675828db6dSBrian Somers #include "bundle.h" 68af57ed9fSAtsushi Murai 69455aabc3SBrian Somers const char * 705e315498SBrian Somers Auth2Nam(u_short auth, u_char type) 71ed6a16c1SPoul-Henning Kamp { 725e315498SBrian Somers static char chap[10]; 735e315498SBrian Somers 74455aabc3SBrian Somers switch (auth) { 75455aabc3SBrian Somers case PROTO_PAP: 76455aabc3SBrian Somers return "PAP"; 77455aabc3SBrian Somers case PROTO_CHAP: 785e315498SBrian Somers snprintf(chap, sizeof chap, "CHAP 0x%02x", type); 795e315498SBrian Somers return chap; 80455aabc3SBrian Somers case 0: 81455aabc3SBrian Somers return "none"; 82d025849cSBrian Somers } 83455aabc3SBrian Somers return "unknown"; 8453c9f6c0SAtsushi Murai } 8553c9f6c0SAtsushi Murai 86d5015272SBrian Somers static int 87d5015272SBrian Somers auth_CheckPasswd(const char *name, const char *data, const char *key) 88d5015272SBrian Somers { 89d5015272SBrian Somers if (!strcmp(data, "*")) { 90d5015272SBrian Somers /* Then look up the real password database */ 91d5015272SBrian Somers struct passwd *pw; 92d5015272SBrian Somers int result; 93d5015272SBrian Somers 94d5015272SBrian Somers result = (pw = getpwnam(name)) && 95d5015272SBrian Somers !strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd); 96d5015272SBrian Somers endpwent(); 97d5015272SBrian Somers return result; 98d5015272SBrian Somers } 99d5015272SBrian Somers 100d5015272SBrian Somers return !strcmp(data, key); 101d5015272SBrian Somers } 102d5015272SBrian Somers 1031ae349f5Scvs2svn int 10492b09558SBrian Somers auth_SetPhoneList(const char *name, char *phone, int phonelen) 10592b09558SBrian Somers { 10692b09558SBrian Somers FILE *fp; 107c39aa54eSBrian Somers int n, lineno; 10892b09558SBrian Somers char *vector[6]; 10992b09558SBrian Somers char buff[LINE_LEN]; 11092b09558SBrian Somers 11192b09558SBrian Somers fp = OpenSecret(SECRETFILE); 112c39aa54eSBrian Somers lineno = 0; 11392b09558SBrian Somers if (fp != NULL) { 11492b09558SBrian Somers while (fgets(buff, sizeof buff, fp)) { 115c39aa54eSBrian Somers lineno++; 11692b09558SBrian Somers if (buff[0] == '#') 11792b09558SBrian Somers continue; 11892b09558SBrian Somers buff[strlen(buff) - 1] = '\0'; 11992b09558SBrian Somers memset(vector, '\0', sizeof vector); 120c39aa54eSBrian Somers if ((n = MakeArgs(buff, vector, VECSIZE(vector))) < 0) 121c39aa54eSBrian Somers log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 12292b09558SBrian Somers if (n < 5) 12392b09558SBrian Somers continue; 12492b09558SBrian Somers if (strcmp(vector[0], name) == 0) { 12592b09558SBrian Somers CloseSecret(fp); 12692b09558SBrian Somers if (*vector[4] == '\0') 12792b09558SBrian Somers return 0; 12892b09558SBrian Somers strncpy(phone, vector[4], phonelen - 1); 12992b09558SBrian Somers phone[phonelen - 1] = '\0'; 13092b09558SBrian Somers return 1; /* Valid */ 13192b09558SBrian Somers } 13292b09558SBrian Somers } 13392b09558SBrian Somers CloseSecret(fp); 13492b09558SBrian Somers } 13592b09558SBrian Somers *phone = '\0'; 13692b09558SBrian Somers return 0; 13792b09558SBrian Somers } 13892b09558SBrian Somers 13992b09558SBrian Somers int 14092b09558SBrian Somers auth_Select(struct bundle *bundle, const char *name) 141944f7098SBrian Somers { 14253c9f6c0SAtsushi Murai FILE *fp; 143c39aa54eSBrian Somers int n, lineno; 1441ae349f5Scvs2svn char *vector[5]; 14586e02934SBrian Somers char buff[LINE_LEN]; 14653c9f6c0SAtsushi Murai 147643f4904SBrian Somers if (*name == '\0') { 148972a1bcfSBrian Somers ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 149643f4904SBrian Somers return 1; 150643f4904SBrian Somers } 151643f4904SBrian Somers 152972a1bcfSBrian Somers #ifndef NORADIUS 153972a1bcfSBrian Somers if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE) { 154972a1bcfSBrian Somers /* We've got a radius IP - it overrides everything */ 155972a1bcfSBrian Somers if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip)) 156972a1bcfSBrian Somers return 0; 157972a1bcfSBrian Somers ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr); 158972a1bcfSBrian Somers /* Continue with ppp.secret in case we've got a new label */ 159972a1bcfSBrian Somers } 160972a1bcfSBrian Somers #endif 161972a1bcfSBrian Somers 162643f4904SBrian Somers fp = OpenSecret(SECRETFILE); 163c39aa54eSBrian Somers lineno = 0; 164d5015272SBrian Somers if (fp != NULL) { 16570ee81ffSBrian Somers while (fgets(buff, sizeof buff, fp)) { 166c39aa54eSBrian Somers lineno++; 16753c9f6c0SAtsushi Murai if (buff[0] == '#') 16853c9f6c0SAtsushi Murai continue; 169501f5480SBrian Somers buff[strlen(buff) - 1] = '\0'; 17070ee81ffSBrian Somers memset(vector, '\0', sizeof vector); 171c39aa54eSBrian Somers if ((n = MakeArgs(buff, vector, VECSIZE(vector))) < 0) 172c39aa54eSBrian Somers log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 1731ae349f5Scvs2svn if (n < 2) 17453c9f6c0SAtsushi Murai continue; 175501f5480SBrian Somers if (strcmp(vector[0], name) == 0) { 1761ae349f5Scvs2svn CloseSecret(fp); 177972a1bcfSBrian Somers #ifndef NORADIUS 178972a1bcfSBrian Somers if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) { 179972a1bcfSBrian Somers #endif 18092b09558SBrian Somers if (n > 2 && *vector[2] && strcmp(vector[2], "*") && 18192b09558SBrian Somers !ipcp_UseHisaddr(bundle, vector[2], 1)) 182643f4904SBrian Somers return 0; 183972a1bcfSBrian Somers ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 184972a1bcfSBrian Somers #ifndef NORADIUS 185972a1bcfSBrian Somers } 186972a1bcfSBrian Somers #endif 18792b09558SBrian Somers if (n > 3 && *vector[3] && strcmp(vector[3], "*")) 18849052c95SBrian Somers bundle_SetLabel(bundle, vector[3]); 189d5015272SBrian Somers return 1; /* Valid */ 19053c9f6c0SAtsushi Murai } 191501f5480SBrian Somers } 19253c9f6c0SAtsushi Murai CloseSecret(fp); 193643f4904SBrian Somers } 194643f4904SBrian Somers 195643f4904SBrian Somers #ifndef NOPASSWDAUTH 196643f4904SBrian Somers /* Let 'em in anyway - they must have been in the passwd file */ 197972a1bcfSBrian Somers ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 198643f4904SBrian Somers return 1; 199643f4904SBrian Somers #else 200972a1bcfSBrian Somers #ifndef NORADIUS 201972a1bcfSBrian Somers if (bundle->radius.valid) 202972a1bcfSBrian Somers return 1; 203972a1bcfSBrian Somers #endif 204972a1bcfSBrian Somers 205972a1bcfSBrian Somers /* Disappeared from ppp.secret ??? */ 206643f4904SBrian Somers return 0; 207643f4904SBrian Somers #endif 20853c9f6c0SAtsushi Murai } 20953c9f6c0SAtsushi Murai 210af57ed9fSAtsushi Murai int 211972a1bcfSBrian Somers auth_Validate(struct bundle *bundle, const char *name, 212643f4904SBrian Somers const char *key, struct physical *physical) 213af57ed9fSAtsushi Murai { 214643f4904SBrian Somers /* Used by PAP routines */ 215643f4904SBrian Somers 216af57ed9fSAtsushi Murai FILE *fp; 217c39aa54eSBrian Somers int n, lineno; 2189c97abd8SBrian Somers char *vector[5]; 21986e02934SBrian Somers char buff[LINE_LEN]; 220af57ed9fSAtsushi Murai 221643f4904SBrian Somers fp = OpenSecret(SECRETFILE); 222c39aa54eSBrian Somers lineno = 0; 223643f4904SBrian Somers if (fp != NULL) { 22470ee81ffSBrian Somers while (fgets(buff, sizeof buff, fp)) { 225c39aa54eSBrian Somers lineno++; 226af57ed9fSAtsushi Murai if (buff[0] == '#') 227af57ed9fSAtsushi Murai continue; 228af57ed9fSAtsushi Murai buff[strlen(buff) - 1] = 0; 22970ee81ffSBrian Somers memset(vector, '\0', sizeof vector); 230c39aa54eSBrian Somers if ((n = MakeArgs(buff, vector, VECSIZE(vector))) < 0) 231c39aa54eSBrian Somers log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 232af57ed9fSAtsushi Murai if (n < 2) 233af57ed9fSAtsushi Murai continue; 234972a1bcfSBrian Somers if (strcmp(vector[0], name) == 0) { 235af57ed9fSAtsushi Murai CloseSecret(fp); 236972a1bcfSBrian Somers return auth_CheckPasswd(name, vector[1], key); 237af57ed9fSAtsushi Murai } 238af57ed9fSAtsushi Murai } 239af57ed9fSAtsushi Murai CloseSecret(fp); 240d5015272SBrian Somers } 241d5015272SBrian Somers 242d5015272SBrian Somers #ifndef NOPASSWDAUTH 2431342caedSBrian Somers if (Enabled(bundle, OPT_PASSWDAUTH)) 244972a1bcfSBrian Somers return auth_CheckPasswd(name, "*", key); 245d5015272SBrian Somers #endif 246d5015272SBrian Somers 247d5015272SBrian Somers return 0; /* Invalid */ 248af57ed9fSAtsushi Murai } 249af57ed9fSAtsushi Murai 250af57ed9fSAtsushi Murai char * 251972a1bcfSBrian Somers auth_GetSecret(struct bundle *bundle, const char *name, int len, 252643f4904SBrian Somers struct physical *physical) 253af57ed9fSAtsushi Murai { 254d5015272SBrian Somers /* Used by CHAP routines */ 255d5015272SBrian Somers 256af57ed9fSAtsushi Murai FILE *fp; 257c39aa54eSBrian Somers int n, lineno; 2589c97abd8SBrian Somers char *vector[5]; 259c506ecd5SBrian Somers static char buff[LINE_LEN]; /* vector[] will point here when returned */ 260af57ed9fSAtsushi Murai 261643f4904SBrian Somers fp = OpenSecret(SECRETFILE); 262af57ed9fSAtsushi Murai if (fp == NULL) 263af57ed9fSAtsushi Murai return (NULL); 264d5015272SBrian Somers 265c39aa54eSBrian Somers lineno = 0; 26670ee81ffSBrian Somers while (fgets(buff, sizeof buff, fp)) { 267c39aa54eSBrian Somers lineno++; 268af57ed9fSAtsushi Murai if (buff[0] == '#') 269af57ed9fSAtsushi Murai continue; 270c506ecd5SBrian Somers n = strlen(buff) - 1; 271c506ecd5SBrian Somers if (buff[n] == '\n') 272c506ecd5SBrian Somers buff[n] = '\0'; /* Trim the '\n' */ 27370ee81ffSBrian Somers memset(vector, '\0', sizeof vector); 274c39aa54eSBrian Somers if ((n = MakeArgs(buff, vector, VECSIZE(vector))) < 0) 275c39aa54eSBrian Somers log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 276af57ed9fSAtsushi Murai if (n < 2) 277af57ed9fSAtsushi Murai continue; 278972a1bcfSBrian Somers if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) { 279643f4904SBrian Somers CloseSecret(fp); 280d5015272SBrian Somers return vector[1]; 281af57ed9fSAtsushi Murai } 282af57ed9fSAtsushi Murai } 283af57ed9fSAtsushi Murai CloseSecret(fp); 284af57ed9fSAtsushi Murai return (NULL); /* Invalid */ 285af57ed9fSAtsushi Murai } 28653c9f6c0SAtsushi Murai 28753c9f6c0SAtsushi Murai static void 288b6e82f33SBrian Somers AuthTimeout(void *vauthp) 28953c9f6c0SAtsushi Murai { 290b6e82f33SBrian Somers struct authinfo *authp = (struct authinfo *)vauthp; 29153c9f6c0SAtsushi Murai 292dd7e2610SBrian Somers timer_Stop(&authp->authtimer); 29353c9f6c0SAtsushi Murai if (--authp->retry > 0) { 294f0cdd9c0SBrian Somers authp->id++; 295f0cdd9c0SBrian Somers (*authp->fn.req)(authp); 296dd7e2610SBrian Somers timer_Start(&authp->authtimer); 297aceaed92SBrian Somers } else { 298aceaed92SBrian Somers log_Printf(LogPHASE, "Auth: No response from server\n"); 299aceaed92SBrian Somers datalink_AuthNotOk(authp->physical->dl); 300aceaed92SBrian Somers } 30153c9f6c0SAtsushi Murai } 30253c9f6c0SAtsushi Murai 30353c9f6c0SAtsushi Murai void 304f0cdd9c0SBrian Somers auth_Init(struct authinfo *authp, struct physical *p, auth_func req, 305f0cdd9c0SBrian Somers auth_func success, auth_func failure) 30653c9f6c0SAtsushi Murai { 307f0cdd9c0SBrian Somers memset(authp, '\0', sizeof(struct authinfo)); 308479508cfSBrian Somers authp->cfg.fsm.timeout = DEF_FSMRETRY; 309479508cfSBrian Somers authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES; 310479508cfSBrian Somers authp->cfg.fsm.maxtrm = 0; /* not used */ 311f0cdd9c0SBrian Somers authp->fn.req = req; 312f0cdd9c0SBrian Somers authp->fn.success = success; 313f0cdd9c0SBrian Somers authp->fn.failure = failure; 314f0cdd9c0SBrian Somers authp->physical = p; 315e2ebb036SBrian Somers } 31653c9f6c0SAtsushi Murai 317e2ebb036SBrian Somers void 318f0cdd9c0SBrian Somers auth_StartReq(struct authinfo *authp) 319e2ebb036SBrian Somers { 320dd7e2610SBrian Somers timer_Stop(&authp->authtimer); 321e2ebb036SBrian Somers authp->authtimer.func = AuthTimeout; 3223b0f8d2eSBrian Somers authp->authtimer.name = "auth"; 323479508cfSBrian Somers authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS; 324e2ebb036SBrian Somers authp->authtimer.arg = (void *)authp; 325479508cfSBrian Somers authp->retry = authp->cfg.fsm.maxreq; 32653c9f6c0SAtsushi Murai authp->id = 1; 327f0cdd9c0SBrian Somers (*authp->fn.req)(authp); 328dd7e2610SBrian Somers timer_Start(&authp->authtimer); 32953c9f6c0SAtsushi Murai } 33053c9f6c0SAtsushi Murai 33153c9f6c0SAtsushi Murai void 332dd7e2610SBrian Somers auth_StopTimer(struct authinfo *authp) 33353c9f6c0SAtsushi Murai { 334dd7e2610SBrian Somers timer_Stop(&authp->authtimer); 335f0cdd9c0SBrian Somers } 336f0cdd9c0SBrian Somers 337f0cdd9c0SBrian Somers struct mbuf * 338f0cdd9c0SBrian Somers auth_ReadHeader(struct authinfo *authp, struct mbuf *bp) 339f0cdd9c0SBrian Somers { 340f0cdd9c0SBrian Somers int len; 341f0cdd9c0SBrian Somers 34226af0ae9SBrian Somers len = m_length(bp); 343f0cdd9c0SBrian Somers if (len >= sizeof authp->in.hdr) { 344f0cdd9c0SBrian Somers bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr); 345f0cdd9c0SBrian Somers if (len >= ntohs(authp->in.hdr.length)) 346f0cdd9c0SBrian Somers return bp; 347b7ff18adSBrian Somers authp->in.hdr.length = htons(0); 348b31a24caSBrian Somers log_Printf(LogWARN, "auth_ReadHeader: Short packet (%d > %d) !\n", 349b31a24caSBrian Somers ntohs(authp->in.hdr.length), len); 350b7ff18adSBrian Somers } else { 351b7ff18adSBrian Somers authp->in.hdr.length = htons(0); 352b31a24caSBrian Somers log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%d > %d) !\n", 353eb2d27cfSBrian Somers (int)(sizeof authp->in.hdr), len); 354b7ff18adSBrian Somers } 355f0cdd9c0SBrian Somers 35626af0ae9SBrian Somers m_freem(bp); 357f0cdd9c0SBrian Somers return NULL; 358f0cdd9c0SBrian Somers } 359f0cdd9c0SBrian Somers 360f0cdd9c0SBrian Somers struct mbuf * 361f0cdd9c0SBrian Somers auth_ReadName(struct authinfo *authp, struct mbuf *bp, int len) 362f0cdd9c0SBrian Somers { 363f0cdd9c0SBrian Somers if (len > sizeof authp->in.name - 1) 364b31a24caSBrian Somers log_Printf(LogWARN, "auth_ReadName: Name too long (%d) !\n", len); 365f0cdd9c0SBrian Somers else { 36626af0ae9SBrian Somers int mlen = m_length(bp); 367f0cdd9c0SBrian Somers 368f0cdd9c0SBrian Somers if (len > mlen) 369b31a24caSBrian Somers log_Printf(LogWARN, "auth_ReadName: Short packet (%d > %d) !\n", 370b31a24caSBrian Somers len, mlen); 371f0cdd9c0SBrian Somers else { 372f0cdd9c0SBrian Somers bp = mbuf_Read(bp, (u_char *)authp->in.name, len); 373f0cdd9c0SBrian Somers authp->in.name[len] = '\0'; 374f0cdd9c0SBrian Somers return bp; 375f0cdd9c0SBrian Somers } 376f0cdd9c0SBrian Somers } 377f0cdd9c0SBrian Somers 378f0cdd9c0SBrian Somers *authp->in.name = '\0'; 37926af0ae9SBrian Somers m_freem(bp); 380f0cdd9c0SBrian Somers return NULL; 38153c9f6c0SAtsushi Murai } 382