Added EAP support with MD5-Challenge and SRP-SHA1 methods. Tested

on Linux (with both methods) and on Solaris (just MD5-Challenge).
Fixed several Makefiles that were missing references to required
modules such as tty.o.
This commit is contained in:
James Carlson 2002-11-02 19:48:13 +00:00
parent 767b224b09
commit d741a3b912
28 changed files with 3797 additions and 317 deletions

149
README.eap-srp Normal file
View File

@ -0,0 +1,149 @@
EAP with MD5-Challenge and SRP-SHA1 support
by James Carlson, Sun Microsystems
Version 2, September 22nd, 2002
1. What it does
The Extensible Authentication Protocol (EAP; RFC 2284) is a
security protocol that can be used with PPP. It provides a means
to plug in multiple optional authentication methods.
This implementation includes the required default MD5-Challenge
method, which is similar to CHAP (RFC 1994), as well as the new
SRP-SHA1 method. This latter method relies on an exchange that is
not vulnerable to dictionary attacks (as is CHAP), does not
require the server to keep a cleartext copy of the secret (as in
CHAP), supports identity privacy, and produces a temporary shared
key that could be used for data encryption.
The SRP-SHA1 method is based on draft-ietf-pppext-eap-srp-03.txt,
a work in progress.
2. Required libraries
Two other packages are required first. Download and install
OpenSSL and Thomas Wu's SRP implementation.
http://www.openssl.org/ (or ftp://ftp.openssl.org/source/)
http://srp.stanford.edu/
Follow the directions in each package to install the SSL and SRP
libraries. Once SRP is installed, you may run tconf as root to
create known fields, if desired. (This step is not required.)
3. Installing the patch
The EAP-SRP patch described here is integrated into this version
of pppd. The following patch may be used with older pppd sources:
ftp://playground.sun.com/carlsonj/eap/ppp-2.4.1-eap-1.tar.gz
Configure, compile, and install as root. You may want to edit
pppd/Makefile after configuring to enable or disable optional
features.
% ./configure
% make
% su
# make install
If you use csh or tcsh, run "rehash" to pick up the new commands.
If you're using Solaris, and you run into trouble with the
pseudonym feature on the server side ("no DES here" shows in the
log file), make sure that you have the "domestic" versions of the
DES libraries linked. You should see "crypt_d" in "ldd
/usr/local/bin/pppd". If you see "crypt_i" instead, then make
sure that /usr/lib/libcrypt.* links to /usr/lib/libcrypt_d.*. (If
you have the international version of Solaris, then you won't have
crypt_d. You might want to find an alternative DES library.)
4. Adding the secrets
On the EAP SRP-SHA1 client side, access to the cleartext secret is
required. This can be done in two ways:
- Enter the client name, server name, and password in the
/etc/ppp/srp-secrets file. This file has the same format as
the existing chap-secrets and pap-secrets files.
clientname servername "secret here"
- Use the "password" option in any of the standard
configuration files (or the command line) to specify the
secret.
password "secret here"
On the EAP SRP-SHA1 server side, a secret verifier is required.
This is a one-way hash of the client's name and password. To
generate this value, run the srp-entry program (see srp-entry(8)).
This program prompts for the client name and the passphrase (the
secret). The output will be an entry, such as the following,
suitable for use in the server's srp-secrets file. Note that if
this is transferred by cut-and-paste, the entry must be a single
line of text in the file.
pppuser srpserver 0:LFDpwg4HBLi4/kWByzbZpW6pE95/iIWBSt7L.DAkHsvwQphtiq0f6reoUy/1LC1qYqjcrV97lCDmQHQd4KIACGgtkhttLdP3KMowvS0wLXLo25FPJeG2sMAUEWu/HlJPn2/gHyh9aT.ZxUs5MsoQ1E61sJkVBc.2qze1CdZiQGTK3qtWRP6DOpM1bfhKtPoVm.g.MiCcTMWzc54xJUIA0mgKtpthE3JrqCc81cXUt4DYi5yBzeeGTqrI0z2/Gj8Jp7pS4Fkq3GmnYjMxnKfQorFXNwl3m7JSaPa8Gj9/BqnorJOsnSMlIhBe6dy4CYytuTbNb4Wv/nFkmSThK782V:2cIyMp1yKslQgE *
The "secret" field consists of three entries separated by colons.
The first entry is the index of the modulus and generator from
SRP's /etc/tpasswd.conf. If the special value 0 is used, then the
well-known modulus/generator value is used (this is recommended,
because it is much faster). The second value is the verifier
value. The third is the password "salt." These latter two values
are encoded in base64 notation.
For EAP MD5-Challenge, both client and server use the existing
/etc/ppp/chap-secrets file.
5. Configuration options
There are two main options relating to EAP available for the
client. These are:
refuse-eap - refuse to authenticate with EAP
srp-use-pseudonym - use the identity privacy if
offered by server
The second option stores a pseudonym, if offered by the EAP
SRP-SHA1 server, in the $HOME/.ppp_pseudonym file. The pseudonym
is typically an encrypted version of the client identity. During
EAP start-up, the pseudonym stored in this file is offered to the
peer as the identity. If this is accepted by the peer, then
eavesdroppers will be unable to determine the identity of the
client. Each time the client is authenticated, the server will
offer a new pseudoname to the client using an obscured (reversibly
encrypted) message. Thus, access across successive sessions
cannot be tracked.
There are two main options for EAP on the server:
require-eap - require client to use EAP
srp-pn-secret "string" - set server's pseudoname secret
The second option sets the long-term secret used on the server to
encrypt the user's identity to produce pseudonames. The
pseudoname is constructed by hashing this string with the current
date (to the nearest day) with SHA1, then using this hash as the
key for a DES encryption of the client's name. The date is added
to the hash for two reasons. First, this allows the pseudonym to
change daily. Second, it allows the server to decode any previous
pseudonym by trying previous dates.
See the pppd(8) man page for additional options.
6. Comments welcome!
This is still an experimental implementation. It has been tested
and reviewed carefully for correctness, but may still be
incomplete or have other flaws. All comments are welcome. Please
address them to the author:
james.d.carlson@sun.com
or, for EAP itself or the SRP extensions to EAP, to the IETF PPP
Extensions working group:
ietf-ppp@merit.edu

14
configure vendored
View File

@ -1,5 +1,5 @@
#!/bin/sh
# $Id: configure,v 1.29 2002/09/07 05:15:25 carlsonj Exp $
# $Id: configure,v 1.30 2002/11/02 19:48:12 carlsonj Exp $
# if [ -d /NextApps ]; then
# system="NeXTStep"
@ -21,8 +21,8 @@ case $system in
# [0-3]*) state="ancient";;
# 4*) state="known"; ksrc="sunos4"; makext="sunos4";;
5.[7-9]*|5.[1-9][0-9]) state="known"; ksrc="solaris"; makext="sol2";
case $arch in
sun4u) archvariant='-64';;
case "`/usr/bin/isainfo -k`" in
sparcv9) archvariant='-64';;
*) ;;
esac;;
5.[1-6]*) state="known"; ksrc="solaris"; makext="sol2";;
@ -33,7 +33,7 @@ case $system in
elif gcc --version >/dev/null 2>&1; then
archvariant=gcc$archvariant
compiletype=.gcc
if [ "$arch" = "sun4u" ]; then
if [ "$archvariant" = "gcc-64" ]; then
( cd /tmp; touch ppp$$.c
gcc -c -m64 ppp$$.c >/dev/null 2>&1 || (
echo "gcc is unable to make 64 bit modules, and your $arch system needs them."
@ -125,10 +125,12 @@ case $state in
echo "This is a newer release of $system than is supported by"
echo "this software. It may or may not work.";;
unknown)
echo "This software has not been ported to this system. Sorry.";;
echo "This software has not been ported to $system. Sorry.";;
notincluded)
echo "Support for this system has not been included"
echo "Support for $system has not been included"
echo "in this distribution. Sorry.";;
known)
echo "Configuring for $system";;
esac
if [ -d "$ksrc" ]; then

View File

@ -1,4 +1,4 @@
/* $Id: ppp_defs.h,v 1.15 2002/05/21 17:26:48 dfs Exp $ */
/* $Id: ppp_defs.h,v 1.16 2002/11/02 19:48:12 carlsonj Exp $ */
/*
* ppp_defs.h - PPP definitions.
@ -85,6 +85,7 @@
#define PPP_LQR 0xc025 /* Link Quality Report protocol */
#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
#define PPP_CBCP 0xc029 /* Callback Control Protocol */
#define PPP_EAP 0xc227 /* Extensible Authentication Protocol */
/*
* Values for FCS calculations.

View File

@ -1,8 +1,8 @@
#
# pppd makefile for NeXT
#
# $Orignial: Makefile.ultrix,v 1.4 1994/09/01 00:40:40 paulus Exp $
# $Id: Makefile.NeXT,v 1.7 2002/05/21 17:26:48 dfs Exp $
# $Original: Makefile.ultrix,v 1.4 1994/09/01 00:40:40 paulus Exp $
# $Id: Makefile.NeXT,v 1.8 2002/11/02 19:48:12 carlsonj Exp $
#
ARCHFLAGS =
@ -10,8 +10,8 @@ ARCHFLAGS =
BINDIR = /usr/local/ppp/bin
MANDIR = /usr/local/ppp/man
OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
ecp.o auth.o options.o demand.o utils.o sys-NeXT.o
OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o eap.o md5.o ccp.o \
ecp.o auth.o options.o demand.o utils.o sys-NeXT.o tty.o
#
# For HPPA and SPARC, define FIXSIGS to get around posix bugs in

View File

@ -1,6 +1,6 @@
#
# pppd makefile for AIX 4.1
# $Id: Makefile.aix4,v 1.5 2002/05/21 17:26:48 dfs Exp $
# $Id: Makefile.aix4,v 1.6 2002/11/02 19:48:12 carlsonj Exp $
#
#ifndef BINDIR
BINDIR = /usr/sbin
@ -10,12 +10,14 @@ MANDIR = /usr/man
#ENDIF
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
ecp.c auth.c options.c demand.c utils.c sys-aix4.c \
gencode.c grammar.c scanner.c nametoaddr.c optimize.c
ecp.c auth.c options.c demand.c utils.c sys-aix4.c eap.c tty.c
PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
ecp.o auth.o options.o demand.o utils.o sys-aix4.o \
gencode.o grammar.o scanner.o nametoaddr.o optimize.o
ecp.o auth.o options.o demand.o utils.o sys-aix4.o eap.o tty.o
# xxx what are these? They're not here.
# gencode.c grammar.c scanner.c nametoaddr.c optimize.c
# gencode.o grammar.o scanner.o nametoaddr.o optimize.o
CC = xlc
DEBUG_FLAGS = -DDEBUGALL

View File

@ -1,4 +1,4 @@
# $Id: Makefile.bsd,v 1.16 2002/05/21 17:26:48 dfs Exp $
# $Id: Makefile.bsd,v 1.17 2002/11/02 19:48:12 carlsonj Exp $
BINDIR?= /usr/sbin
# -D_BITYPES is for FreeBSD, which doesn't define anything to
@ -8,7 +8,7 @@ CFLAGS+= -g -I../include -DHAVE_PATHS_H -D_BITYPES
PROG= pppd
SRCS= main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
ecp.c demand.c auth.c options.c utils.c sys-bsd.c
ecp.c demand.c auth.c options.c utils.c sys-bsd.c eap.c tty.c
MAN= pppd.cat8
MAN8= pppd.8
BINMODE=4555

View File

@ -1,6 +1,6 @@
#
# pppd makefile for Linux
# $Id: Makefile.linux,v 1.53 2002/10/27 12:56:26 fcusack Exp $
# $Id: Makefile.linux,v 1.54 2002/11/02 19:48:12 carlsonj Exp $
#
# Default installation locations
@ -8,19 +8,19 @@ BINDIR = $(DESTDIR)/usr/sbin
MANDIR = $(DESTDIR)/usr/man
INCDIR = $(DESTDIR)/usr/include
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c ecp.c \
ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c cbcp.c \
demand.c utils.c tty.c sha1.c
TARGETS = pppd
HEADERS = cbcp.h ccp.h chap.h chap_ms.h ecp.h fsm.h ipcp.h \
ipxcp.h lcp.h magic.h md4.h md5.h patchlevel.h pathnames.h pppd.h \
sha1.h tdb.h upap.h
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c ecp.c \
ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c \
demand.c utils.c tty.c eap.c
HEADERS = ccp.h chap.h ecp.h fsm.h ipcp.h \
ipxcp.h lcp.h magic.h md5.h patchlevel.h pathnames.h pppd.h \
upap.h eap.h
MANPAGES = pppd.8
PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \
auth.o options.o demand.o utils.o sys-linux.o ipxcp.o tty.o sha1.o
all: pppd
auth.o options.o demand.o utils.o sys-linux.o ipxcp.o tty.o eap.o
#
# include dependencies if present
@ -33,14 +33,11 @@ endif
COPTS = -O2 -pipe -Wall -g
LIBS =
ifneq ($(wildcard /usr/lib/libcrypt.*),)
LIBS += -lcrypt
endif
# Uncomment the next 2 lines to include support for Microsoft's
# MS-CHAP authentication protocol. Also, edit plugins/radius/Makefile.linux.
CHAPMS=y
USE_CRYPT=y
MSLANMAN=y
# Uncomment the next line to include support for MPPE. CHAPMS (above) must
# also be enabled. Also, edit plugins/radius/Makefile.linux.
MPPE=y
@ -68,10 +65,15 @@ HAS_SHADOW=y
#USE_PAM=y
#HAVE_INET6=y
# Enable plugins
PLUGIN=y
# Enable Microsoft proprietary Callback Control Protocol
#CBCP=y
# Enable EAP SRP-SHA1 authentication (requires libsrp)
USE_SRP=y
MAXOCTETS=y
INCLUDE_DIRS= -I../include
@ -82,15 +84,9 @@ CFLAGS= $(COPTS) $(COMPILE_FLAGS) $(INCLUDE_DIRS)
ifdef CHAPMS
CFLAGS += -DCHAPMS=1
ifndef USE_CRYPT
LIBS := -ldes $(LIBS)
else
CFLAGS += -DUSE_CRYPT=1
ifneq ($(wildcard /usr/include/crypt.h),)
CFLAGS += -DHAVE_CRYPT_H=1
endif
endif
NEEDDES=y
PPPDOBJS += md4.o chap_ms.o
HEADERS += md4.h chap_ms.h
ifdef MSLANMAN
CFLAGS += -DMSLANMAN=1
endif
@ -99,15 +95,49 @@ CFLAGS += -DMPPE=1
endif
endif
# EAP SRP-SHA1
ifdef USE_SRP
CFLAGS += -DUSE_SRP -DOPENSSL -I/usr/local/ssl/include
LIBS += -lsrp -L/usr/local/ssl/lib -lcrypto
TARGETS += srp-entry
EXTRAINSTALL = $(INSTALL) -s -c -m 555 srp-entry $(BINDIR)/srp-entry
MANPAGES += srp-entry.8
EXTRACLEAN += srp-entry.o
NEEDDES=y
else
# OpenSSL has an integrated version of SHA-1, and its implementation
# is incompatible with this local SHA-1 implementation. We must use
# one or the other, not both.
PPPDSRCS += sha1.c
HEADERS += sha1.h
PPPDOBJS += sha1.o
endif
ifdef HAS_SHADOW
CFLAGS += -DHAS_SHADOW
#LIBS := -lshadow $(LIBS)
#LIBS += -lshadow $(LIBS)
endif
ifdef NEEDDES
ifndef USE_CRYPT
LIBS += -ldes $(LIBS)
else
CFLAGS += -DUSE_CRYPT=1
ifneq ($(wildcard /usr/include/crypt.h),)
CFLAGS += -DHAVE_CRYPT_H=1
endif
ifneq ($(wildcard /usr/lib/libcrypt.*),)
LIBS += -lcrypt
endif
endif
PPPDOBJS += pppcrypt.o
HEADERS += pppcrypt.h
endif
# For "Pluggable Authentication Modules", see ftp.redhat.com:/pub/pam/.
ifdef USE_PAM
CFLAGS += -DUSE_PAM
LIBS := -lpam -ldl $(LIBS)
LIBS += -lpam -ldl
endif
# Multi-linnk
@ -125,11 +155,12 @@ ifdef USE_TDB
CFLAGS += -DUSE_TDB=1
PPPDSRCS += tdb.c
PPPDOBJS += tdb.o
HEADERS += tdb.h
endif
# Lock library binary for Linux is included in 'linux' subdirectory.
ifdef LOCKLIB
LIBS := -llock $(LIBS)
LIBS += -llock
CFLAGS += -DLOCKLIB=1
endif
@ -152,8 +183,10 @@ ifdef HAVE_INET6
endif
ifdef CBCP
PPPDSRCS += cbcp.c
PPPDOBJS += cbcp.o
CFLAGS += -DCBCP_SUPPORT
HEADERS += cbcp.h
endif
ifdef MAXOCTETS
@ -162,8 +195,11 @@ endif
INSTALL= install -o root
all: $(TARGETS)
install: pppd
mkdir -p $(BINDIR) $(MANDIR)
$(EXTRAINSTALL)
$(INSTALL) -s -c -m 555 pppd $(BINDIR)/pppd
if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \
chmod o-rx,u+s $(BINDIR)/pppd; fi
@ -172,12 +208,15 @@ install: pppd
pppd: $(PPPDOBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o pppd $(PPPDOBJS) $(LIBS)
srp-entry: srp-entry.c
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ srp-entry.c $(LIBS)
install-devel:
mkdir -p $(INCDIR)/pppd
$(INSTALL) -c -m 644 $(HEADERS) $(INCDIR)/pppd
clean:
rm -f $(PPPDOBJS) pppd *~ #* core
rm -f $(PPPDOBJS) $(EXTRACLEAN) $(TARGETS) *~ #* core
depend:
$(CPP) -M $(CFLAGS) $(PPPDSRCS) >.depend

View File

@ -4,7 +4,8 @@ PCAPDIR=${.CURDIR}/../../lib/libpcap
PROG= pppd
SRCS= auth.c cbcp.c ccp.c ecp.c chap.c chap_ms.c demand.c fsm.c ipcp.c \
ipxcp.c lcp.c magic.c main.c options.c sys-bsd.c upap.c
ipxcp.c lcp.c magic.c main.c options.c sys-bsd.c upap.c eap.c tty.c \
utils.c
.PATH: ${PCAPDIR} ${.CURDIR}/../../sys/net
MAN= pppd.8 pppd.cbcp.8
@ -12,6 +13,7 @@ SUBDIR= pppstats chat
BINMODE=4555
BINOWN= root
# pick up md5, md4, and sha1
LDADD= -lpcap -lcrypt -lutil
DPADD= ${LIBPCAP} ${LIBCRYPT} ${LIBUTIL}
CFLAGS+= -I. -I../include -DHAVE_PATHS_H -I${PCAPDIR} -DPPP_FILTER

View File

@ -1,16 +1,18 @@
#
# pppd makefile for OSF/1 on DEC Alpha
# $Id: Makefile.osf,v 1.12 2002/05/21 17:26:48 dfs Exp $
# $Id: Makefile.osf,v 1.13 2002/11/02 19:48:12 carlsonj Exp $
#
BINDIR = /usr/local/etc
MANDIR = /usr/local/man
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c ecp.c \
auth.c options.c demand.c utils.c sys-osf.c md4.c chap_ms.c sha1.c
auth.c options.c demand.c utils.c sys-osf.c md4.c chap_ms.c sha1.c \
eap.c tty.c
PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \
auth.o options.o demand.o utils.o sys-osf.o md4.o chap_ms.o sha1.o
auth.o options.o demand.o utils.o sys-osf.o md4.o chap_ms.o sha1.o \
eap.o tty.o
CC = cc
#DEBUG_FLAGS = -DDEBUGALL

View File

@ -1,6 +1,6 @@
#
# Makefile for pppd under Solaris 2.
# $Id: Makefile.sol2,v 1.22 2002/09/07 05:15:25 carlsonj Exp $
# $Id: Makefile.sol2,v 1.23 2002/11/02 19:48:12 carlsonj Exp $
#
include ../Makedefs.com
@ -8,8 +8,8 @@ include ../Makedefs.com
CFLAGS = -I../include -DSVR4 -DSOL2 $(COPTS)
LIBS = -lsocket -lnsl
OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o tty.o \
ccp.o ecp.o auth.o options.o demand.o utils.o sys-solaris.o tdb.o
OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o eap.o md5.o tty.o \
ccp.o ecp.o auth.o options.o demand.o utils.o sys-solaris.o
#
# uncomment the following to enable plugins

View File

@ -1,6 +1,6 @@
#
# Makefile for pppd under SunOS 4.
# $Id: Makefile.sunos4,v 1.12 2002/05/21 17:26:48 dfs Exp $
# $Id: Makefile.sunos4,v 1.13 2002/11/02 19:48:12 carlsonj Exp $
#
include ../sunos4/Makedefs
@ -13,7 +13,7 @@ CFLAGS = $(COPTS) -I../include -DSUNOS4 -DGIDSET_TYPE=int \
all: pppd
OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \
auth.o options.o demand.o utils.o sys-sunos4.o tty.o
auth.o options.o demand.o utils.o sys-sunos4.o tty.o eap.o
pppd: $(OBJS)
$(CC) -o pppd $(OBJS) $(LIBS)

View File

@ -1,6 +1,6 @@
#
# Makefile for pppd under Solaris 2.
# $Id: Makefile.svr4,v 1.15 2002/05/21 17:26:48 dfs Exp $
# Makefile for pppd on generic System V release 4
# $Id: Makefile.svr4,v 1.16 2002/11/02 19:48:12 carlsonj Exp $
#
include ../svr4/Makedefs
@ -11,7 +11,7 @@ LIBS = -lsocket -lnsl -lc -L/usr/ucblib -lucb
all: pppd
OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \
auth.o options.o demand.o utils.o sys-svr4.o
auth.o options.o demand.o utils.o sys-svr4.o eap.o tty.o
pppd: $(OBJS)
$(CC) -o pppd $(OBJS) $(LIBS)

View File

@ -1,16 +1,16 @@
#
# pppd makefile for Ultrix
# $Id: Makefile.ultrix,v 1.12 2002/05/21 17:26:49 dfs Exp $
# $Id: Makefile.ultrix,v 1.13 2002/11/02 19:48:12 carlsonj Exp $
#
BINDIR = /usr/local/etc
MANDIR = /usr/local/man
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c ecp.c \
auth.c options.c demand.c utils.c sys-ultrix.c
auth.c options.c demand.c utils.c sys-ultrix.c eap.c tty.c
PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \
auth.o options.o demand.o utils.o sys-ultrix.o
auth.o options.o demand.o utils.o sys-ultrix.o eap.o tty.o
# CC = gcc
DEBUG_FLAGS =

View File

@ -32,7 +32,7 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#define RCSID "$Id: auth.c,v 1.88 2002/10/27 12:56:26 fcusack Exp $"
#define RCSID "$Id: auth.c,v 1.89 2002/11/02 19:48:12 carlsonj Exp $"
#include <stdio.h>
#include <stddef.h>
@ -74,6 +74,7 @@
#include "ipcp.h"
#include "upap.h"
#include "chap.h"
#include "eap.h"
#ifdef CBCP_SUPPORT
#include "cbcp.h"
#endif
@ -180,6 +181,7 @@ bool uselogin = 0; /* Use /etc/passwd for checking PAP */
bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */
bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */
bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */
bool refuse_eap = 0; /* Don't wanna auth. ourselves with EAP */
#ifdef CHAPMS
bool refuse_mschap = 0; /* Don't wanna auth. ourselves with MS-CHAP */
bool refuse_mschap_v2 = 0; /* Don't wanna auth. ourselves with MS-CHAPv2 */
@ -208,10 +210,12 @@ static int null_login __P((int));
static int get_pap_passwd __P((char *));
static int have_pap_secret __P((int *));
static int have_chap_secret __P((char *, char *, int, int *));
static int have_srp_secret __P((char *client, char *server, int need_ip,
int *lacks_ipp));
static int ip_addr_check __P((u_int32_t, struct permitted_ip *));
static int scan_authfile __P((FILE *, char *, char *, char *,
struct wordlist **, struct wordlist **,
char *));
char *, int));
static void free_wordlist __P((struct wordlist *));
static void auth_script __P((char *));
static void auth_script_done __P((void *));
@ -301,6 +305,12 @@ option_t auth_options[] = {
&lcp_allowoptions[0].chap_mdtype },
#endif
{ "require-eap", o_bool, &lcp_wantoptions[0].neg_eap,
"Require EAP authentication from peer", OPT_PRIOSUB | 1,
&auth_required },
{ "refuse-eap", o_bool, &refuse_eap,
"Don't agree to authenticate to peer with EAP", 1 },
{ "name", o_string, our_name,
"Set local name for authentication",
OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN },
@ -554,7 +564,7 @@ link_established(unit)
&& protp->lowerup != NULL)
(*protp->lowerup)(unit);
if (auth_required && !(go->neg_upap || go->neg_chap)) {
if (auth_required && !(go->neg_upap || go->neg_chap || go->neg_eap)) {
/*
* We wanted the peer to authenticate itself, and it refused:
* if we have some address(es) it can use without auth, fine,
@ -575,14 +585,20 @@ link_established(unit)
new_phase(PHASE_AUTHENTICATE);
used_login = 0;
auth = 0;
if (go->neg_chap) {
if (go->neg_eap) {
eap_authpeer(unit, our_name);
auth |= EAP_PEER;
} else if (go->neg_chap) {
ChapAuthPeer(unit, our_name, CHAP_DIGEST(go->chap_mdtype));
auth |= CHAP_PEER;
} else if (go->neg_upap) {
upap_authpeer(unit);
auth |= PAP_PEER;
}
if (ho->neg_chap) {
if (ho->neg_eap) {
eap_authwithpeer(unit, user);
auth |= EAP_WITHPEER;
} else if (ho->neg_chap) {
ChapAuthWithPeer(unit, user, CHAP_DIGEST(ho->chap_mdtype));
auth |= CHAP_WITHPEER;
} else if (ho->neg_upap) {
@ -617,7 +633,7 @@ network_phase(unit)
/*
* If the peer had to authenticate, run the auth-up script now.
*/
if (go->neg_chap || go->neg_upap) {
if (go->neg_chap || go->neg_upap || go->neg_eap) {
notify(auth_up_notifier, 0);
auth_state = s_up;
if (auth_script_state == s_down && auth_script_pid == 0) {
@ -755,6 +771,9 @@ auth_peer_success(unit, protocol, prot_flavor, name, namelen)
case PPP_PAP:
bit = PAP_PEER;
break;
case PPP_EAP:
bit = EAP_PEER;
break;
default:
warn("auth_peer_success: unknown protocol %x", protocol);
return;
@ -830,6 +849,9 @@ auth_withpeer_success(unit, protocol, prot_flavor)
BZERO(passwd, MAXSECRETLEN);
bit = PAP_WITHPEER;
break;
case PPP_EAP:
bit = EAP_WITHPEER;
break;
default:
warn("auth_withpeer_success: unknown protocol %x", protocol);
bit = 0;
@ -1032,28 +1054,35 @@ auth_check_options()
if (wo->chap_mdtype)
wo->neg_chap = 1;
/* If authentication is required, ask peer for CHAP or PAP. */
/* If authentication is required, ask peer for CHAP, PAP, or EAP. */
if (auth_required) {
allow_any_ip = 0;
if (!wo->neg_chap && !wo->neg_upap) {
if (!wo->neg_chap && !wo->neg_upap && !wo->neg_eap) {
wo->neg_chap = 1; wo->chap_mdtype = MDTYPE_ALL;
wo->neg_upap = 1;
wo->neg_eap = 1;
}
} else {
wo->neg_chap = 0; wo->chap_mdtype = MDTYPE_NONE;
wo->neg_upap = 0;
wo->neg_eap = 0;
}
/*
* Check whether we have appropriate secrets to use
* to authenticate the peer.
* to authenticate the peer. Note that EAP can authenticate by way
* of a CHAP-like exchanges as well as SRP.
*/
lacks_ip = 0;
can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip));
if (!can_auth && (wo->neg_chap)) {
if (!can_auth && (wo->neg_chap || wo->neg_eap)) {
can_auth = have_chap_secret((explicit_remote? remote_name: NULL),
our_name, 1, &lacks_ip);
}
if (!can_auth && wo->neg_eap) {
can_auth = have_srp_secret((explicit_remote? remote_name: NULL),
our_name, 1, &lacks_ip);
}
if (auth_required && !can_auth && noauth_addrs == NULL) {
if (default_auth) {
@ -1088,21 +1117,36 @@ auth_reset(unit)
int unit;
{
lcp_options *go = &lcp_gotoptions[unit];
lcp_options *ao = &lcp_allowoptions[0];
lcp_options *ao = &lcp_allowoptions[unit];
int hadchap;
hadchap = -1;
ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL));
ao->neg_chap = (!refuse_chap || !refuse_mschap || !refuse_mschap_v2)
&& (passwd[0] != 0
|| have_chap_secret(user, (explicit_remote? remote_name: NULL),
0, NULL));
&& (passwd[0] != 0 ||
(hadchap = have_chap_secret(user, (explicit_remote? remote_name:
NULL), 0, NULL)));
ao->neg_eap = !refuse_eap && (
passwd[0] != 0 ||
(hadchap == 1 || (hadchap == -1 && have_chap_secret(user,
(explicit_remote? remote_name: NULL), 0, NULL))) ||
have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL));
hadchap = -1;
if (go->neg_upap && !uselogin && !have_pap_secret(NULL))
go->neg_upap = 0;
if (go->neg_chap) {
if (!have_chap_secret((explicit_remote? remote_name: NULL),
our_name, 1, NULL))
if (!(hadchap = have_chap_secret((explicit_remote? remote_name: NULL),
our_name, 1, NULL)))
go->neg_chap = 0;
}
if (go->neg_eap &&
(hadchap == 0 || (hadchap == -1 &&
!have_chap_secret((explicit_remote? remote_name: NULL), our_name,
1, NULL))) &&
!have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1,
NULL))
go->neg_eap = 0;
}
@ -1173,7 +1217,7 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg)
} else {
check_access(f, filename);
if (scan_authfile(f, user, our_name, secret, &addrs, &opts, filename) < 0) {
if (scan_authfile(f, user, our_name, secret, &addrs, &opts, filename, 0) < 0) {
warn("no PAP secret found for %s", user);
} else {
/*
@ -1248,8 +1292,12 @@ static pam_handle_t *pamh = NULL;
* echo off means password.
*/
static int PAM_conv (int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
static int PAM_conv (int num_msg,
#ifndef SOL2
const
#endif
struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int replies = 0;
struct pam_response *reply = NULL;
@ -1486,7 +1534,7 @@ null_login(unit)
return 0;
check_access(f, filename);
i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename);
i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0);
ret = i >= 0 && secret[0] == 0;
BZERO(secret, sizeof(secret));
fclose(f);
@ -1534,7 +1582,7 @@ get_pap_passwd(passwd)
check_access(f, filename);
ret = scan_authfile(f, user,
(remote_name[0]? remote_name: NULL),
secret, NULL, NULL, filename);
secret, NULL, NULL, filename, 0);
fclose(f);
if (ret < 0)
return 0;
@ -1571,7 +1619,7 @@ have_pap_secret(lacks_ipp)
return 0;
ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name,
NULL, &addrs, NULL, filename);
NULL, &addrs, NULL, filename, 0);
fclose(f);
if (ret >= 0 && !some_ip_ok(addrs)) {
if (lacks_ipp != 0)
@ -1620,7 +1668,49 @@ have_chap_secret(client, server, need_ip, lacks_ipp)
else if (server != NULL && server[0] == 0)
server = NULL;
ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename);
ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0);
fclose(f);
if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
if (lacks_ipp != 0)
*lacks_ipp = 1;
ret = -1;
}
if (addrs != 0)
free_wordlist(addrs);
return ret >= 0;
}
/*
* have_srp_secret - check whether we have a SRP file with a
* secret that we could possibly use for authenticating `client'
* on `server'. Either can be the null string, meaning we don't
* know the identity yet.
*/
static int
have_srp_secret(client, server, need_ip, lacks_ipp)
char *client;
char *server;
int need_ip;
int *lacks_ipp;
{
FILE *f;
int ret;
char *filename;
struct wordlist *addrs;
filename = _PATH_SRPFILE;
f = fopen(filename, "r");
if (f == NULL)
return 0;
if (client != NULL && client[0] == 0)
client = NULL;
else if (server != NULL && server[0] == 0)
server = NULL;
ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0);
fclose(f);
if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
if (lacks_ipp != 0)
@ -1674,7 +1764,7 @@ get_secret(unit, client, server, secret, secret_len, am_server)
}
check_access(f, filename);
ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename);
ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0);
fclose(f);
if (ret < 0)
return 0;
@ -1699,6 +1789,56 @@ get_secret(unit, client, server, secret, secret_len, am_server)
return 1;
}
/*
* get_srp_secret - open the SRP secret file and return the secret
* for authenticating the given client on the given server.
* (We could be either client or server).
*/
int
get_srp_secret(unit, client, server, secret, am_server)
int unit;
char *client;
char *server;
char *secret;
int am_server;
{
FILE *fp;
int ret;
char *filename;
struct wordlist *addrs, *opts;
if (!am_server && passwd[0] != '\0') {
strlcpy(secret, passwd, MAXWORDLEN);
} else {
filename = _PATH_SRPFILE;
addrs = NULL;
fp = fopen(filename, "r");
if (fp == NULL) {
error("Can't open srp secret file %s: %m", filename);
return 0;
}
check_access(fp, filename);
secret[0] = '\0';
ret = scan_authfile(fp, client, server, secret, &addrs, &opts,
filename, am_server);
fclose(fp);
if (ret < 0)
return 0;
if (am_server)
set_allowed_addrs(unit, addrs, opts);
else if (opts != NULL)
free_wordlist(opts);
if (addrs != NULL)
free_wordlist(addrs);
}
return 1;
}
/*
* set_allowed_addrs() - set the list of allowed addresses.
* Also looks for `--' indicating options to apply for this peer
@ -1986,9 +2126,11 @@ check_access(f, filename)
* following words (extra options) are placed in a wordlist and
* returned in *opts.
* We assume secret is NULL or points to MAXWORDLEN bytes of space.
* Flags are non-zero if we need two colons in the secret in order to
* match.
*/
static int
scan_authfile(f, client, server, secret, addrs, opts, filename)
scan_authfile(f, client, server, secret, addrs, opts, filename, flags)
FILE *f;
char *client;
char *server;
@ -1996,6 +2138,7 @@ scan_authfile(f, client, server, secret, addrs, opts, filename)
struct wordlist **addrs;
struct wordlist **opts;
char *filename;
int flags;
{
int newline, xxx;
int got_flag, best_flag;
@ -2004,6 +2147,7 @@ scan_authfile(f, client, server, secret, addrs, opts, filename)
char word[MAXWORDLEN];
char atfile[MAXWORDLEN];
char lsecret[MAXWORDLEN];
char *cp;
if (addrs != NULL)
*addrs = NULL;
@ -2062,6 +2206,14 @@ scan_authfile(f, client, server, secret, addrs, opts, filename)
if (newline)
continue;
/*
* SRP-SHA1 authenticator should never be reading secrets from
* a file. (Authenticatee may, though.)
*/
if (flags && ((cp = strchr(word, ':')) == NULL ||
strchr(cp + 1, ':') == NULL))
continue;
if (secret != NULL) {
/*
* Special syntax: @/pathname means read secret from file.

View File

@ -40,7 +40,7 @@
* Copyright (c) 2002 Google, Inc.
*/
#define RCSID "$Id: chap_ms.c,v 1.22 2002/09/06 22:11:12 kad Exp $"
#define RCSID "$Id: chap_ms.c,v 1.23 2002/11/02 19:48:12 carlsonj Exp $"
#ifdef CHAPMS
@ -51,19 +51,13 @@
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#include "pppd.h"
#include "chap.h"
#include "chap_ms.h"
#include "md4.h"
#include "sha1.h"
#ifndef USE_CRYPT
#include <des.h>
#endif
#include "pppcrypt.h"
static const char rcsid[] = RCSID;
@ -72,9 +66,6 @@ static void ChallengeHash __P((u_char[16], u_char *, char *, u_char[8]));
static void ascii2unicode __P((char[], int, u_char[]));
static void NTPasswordHash __P((char *, int, u_char[MD4_SIGNATURE_SIZE]));
static void ChallengeResponse __P((u_char *, u_char *, u_char[24]));
static void DesEncrypt __P((u_char *, u_char *, u_char[8]));
static void MakeKey __P((u_char *, u_char *));
static u_char Get7Bits __P((u_char *, int));
static void ChapMS_NT __P((u_char *, char *, int, u_char[24]));
static void ChapMS2_NT __P((char *, u_char[16], char *, char *, int,
u_char[24]));
@ -85,11 +76,6 @@ static void GenerateAuthenticatorResponse __P((char*, int, u_char[24],
static void ChapMS_LANMan __P((u_char *, char *, int, MS_ChapResponse *));
#endif
#ifdef USE_CRYPT
static void Expand __P((u_char *, u_char *));
static void Collapse __P((u_char *, u_char *));
#endif
#ifdef MPPE
static void Set_Start_Key __P((u_char *, char *, int));
static void SetMasterKeys __P((char *, int, u_char[24], int));
@ -112,7 +98,7 @@ ChallengeResponse(u_char *challenge,
u_char PasswordHash[MD4_SIGNATURE_SIZE],
u_char response[24])
{
char ZPasswordHash[21];
u_char ZPasswordHash[21];
BZERO(ZPasswordHash, sizeof(ZPasswordHash));
BCOPY(PasswordHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
@ -122,138 +108,18 @@ ChallengeResponse(u_char *challenge,
sizeof(ZPasswordHash), ZPasswordHash);
#endif
DesEncrypt(challenge, ZPasswordHash + 0, &response[0]);
DesEncrypt(challenge, ZPasswordHash + 7, &response[8]);
DesEncrypt(challenge, ZPasswordHash + 14, &response[16]);
(void) DesSetkey(ZPasswordHash + 0);
DesEncrypt(challenge, response + 0);
(void) DesSetkey(ZPasswordHash + 7);
DesEncrypt(challenge, response + 8);
(void) DesSetkey(ZPasswordHash + 14);
DesEncrypt(challenge, response + 16);
#if 0
dbglog("ChallengeResponse - response %.24B", response);
#endif
}
#ifdef USE_CRYPT
static void
DesEncrypt(u_char *clear, u_char *key, u_char cipher[8])
{
u_char des_key[8];
u_char crypt_key[66];
u_char des_input[66];
MakeKey(key, des_key);
Expand(des_key, crypt_key);
setkey(crypt_key);
#if 0
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
#endif
Expand(clear, des_input);
encrypt(des_input, 0);
Collapse(des_input, cipher);
#if 0
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
#endif
}
#else /* USE_CRYPT */
static void
DesEncrypt(u_char *clear, u_char *key, u_char cipher[8])
{
des_cblock des_key;
des_key_schedule key_schedule;
MakeKey(key, des_key);
des_set_key(&des_key, key_schedule);
#if 0
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
#endif
des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
#if 0
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
#endif
}
#endif /* USE_CRYPT */
static u_char Get7Bits(u_char *input, int startBit)
{
register unsigned int word;
word = (unsigned)input[startBit / 8] << 8;
word |= (unsigned)input[startBit / 8 + 1];
word >>= 15 - (startBit % 8 + 7);
return word & 0xFE;
}
#ifdef USE_CRYPT
/* in == 8-byte string (expanded version of the 56-bit key)
* out == 64-byte string where each byte is either 1 or 0
* Note that the low-order "bit" is always ignored by by setkey()
*/
static void Expand(u_char *in, u_char *out)
{
int j, c;
int i;
for(i = 0; i < 64; in++){
c = *in;
for(j = 7; j >= 0; j--)
*out++ = (c >> j) & 01;
i += 8;
}
}
/* The inverse of Expand
*/
static void Collapse(u_char *in, u_char *out)
{
int j;
int i;
unsigned int c;
for (i = 0; i < 64; i += 8, out++) {
c = 0;
for (j = 7; j >= 0; j--, in++)
c |= *in << j;
*out = c & 0xff;
}
}
#endif
static void MakeKey(u_char *key, u_char *des_key)
{
des_key[0] = Get7Bits(key, 0);
des_key[1] = Get7Bits(key, 7);
des_key[2] = Get7Bits(key, 14);
des_key[3] = Get7Bits(key, 21);
des_key[4] = Get7Bits(key, 28);
des_key[5] = Get7Bits(key, 35);
des_key[6] = Get7Bits(key, 42);
des_key[7] = Get7Bits(key, 49);
#ifndef USE_CRYPT
des_set_odd_parity((des_cblock *)des_key);
#endif
#if 0
CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key));
CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key));
#endif
}
static void
ChallengeHash(u_char PeerChallenge[16], u_char *rchallenge,
char *username, u_char Challenge[8])
@ -348,7 +214,7 @@ static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
static void
ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
u_char LMResponse[24])
MS_ChapResponse *LMResponse)
{
int i;
u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
@ -358,8 +224,10 @@ ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
BZERO(UcasePassword, sizeof(UcasePassword));
for (i = 0; i < secret_len; i++)
UcasePassword[i] = (u_char)toupper(secret[i]);
DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
(void) DesSetkey(UcasePassword + 0);
DesEncrypt( StdText, PasswordHash + 0 );
(void) DesSetkey(UcasePassword + 7);
DesEncrypt( StdText, PasswordHash + 8 );
ChallengeResponse(rchallenge, PasswordHash, LMResponse);
}
#endif

2428
pppd/eap.c Normal file

File diff suppressed because it is too large Load Diff

154
pppd/eap.h Normal file
View File

@ -0,0 +1,154 @@
/*
* eap.h - Extensible Authentication Protocol for PPP (RFC 2284)
*
* Copyright (c) 2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* Non-exclusive rights to redistribute, modify, translate, and use
* this software in source and binary forms, in whole or in part, is
* hereby granted, provided that the above copyright notice is
* duplicated in any source form, and that neither the name of the
* copyright holder nor the author is used to endorse or promote
* products derived from this software.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Original version by James Carlson
*
* $Id: eap.h,v 1.1 2002/11/02 19:48:12 carlsonj Exp $
*/
#ifndef PPP_EAP_H
#define PPP_EAP_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* Packet header = Code, id, length.
*/
#define EAP_HEADERLEN 4
/* EAP message codes. */
#define EAP_REQUEST 1
#define EAP_RESPONSE 2
#define EAP_SUCCESS 3
#define EAP_FAILURE 4
/* EAP types */
#define EAPT_IDENTITY 1
#define EAPT_NOTIFICATION 2
#define EAPT_NAK 3 /* (response only) */
#define EAPT_MD5CHAP 4
#define EAPT_OTP 5 /* One-Time Password; RFC 1938 */
#define EAPT_TOKEN 6 /* Generic Token Card */
/* 7 and 8 are unassigned. */
#define EAPT_RSA 9 /* RSA Public Key Authentication */
#define EAPT_DSS 10 /* DSS Unilateral */
#define EAPT_KEA 11 /* KEA */
#define EAPT_KEA_VALIDATE 12 /* KEA-VALIDATE */
#define EAPT_TLS 13 /* EAP-TLS */
#define EAPT_DEFENDER 14 /* Defender Token (AXENT) */
#define EAPT_W2K 15 /* Windows 2000 EAP */
#define EAPT_ARCOT 16 /* Arcot Systems */
#define EAPT_CISCOWIRELESS 17 /* Cisco Wireless */
#define EAPT_NOKIACARD 18 /* Nokia IP smart card */
#define EAPT_SRP 19 /* Secure Remote Password */
/* 20 is deprecated */
/* EAP SRP-SHA1 Subtypes */
#define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */
#define EAPSRP_CKEY 1 /* Response 1 - Client Key */
#define EAPSRP_SKEY 2 /* Request 2 - Server Key */
#define EAPSRP_CVALIDATOR 2 /* Response 2 - Client Validator */
#define EAPSRP_SVALIDATOR 3 /* Request 3 - Server Validator */
#define EAPSRP_ACK 3 /* Response 3 - final ack */
#define EAPSRP_LWRECHALLENGE 4 /* Req/resp 4 - Lightweight rechal */
#define SRPVAL_EBIT 0x00000001 /* Use shared key for ECP */
#define SRP_PSEUDO_ID "pseudo_"
#define SRP_PSEUDO_LEN 7
enum eap_state_code {
eapInitial = 0, /* No EAP authentication yet requested */
eapPending, /* Waiting for LCP (no timer) */
eapClosed, /* Authentication not in use */
eapListen, /* Client ready (and timer running) */
eapIdentify, /* EAP Identify sent */
eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */
eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */
eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */
eapMD5Chall, /* Sent MD5-Challenge */
eapOpen, /* Completed authentication */
eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */
eapBadAuth /* Failed authentication */
};
#define EAP_STATES \
"Initial", "Pending", "Closed", "Listen", "Identify", \
"SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth"
#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen)
#define eap_server_active(esp) \
((esp)->es_server.ea_state >= eapIdentify && \
(esp)->es_server.ea_state <= eapMD5Chall)
struct eap_auth {
char *ea_name; /* Our name */
char *ea_peer; /* Peer's name */
void *ea_session; /* Authentication library linkage */
u_char *ea_skey; /* Shared encryption key */
int ea_timeout; /* Time to wait (for retransmit/fail) */
int ea_maxrequests; /* Max Requests allowed */
u_short ea_namelen; /* Length of our name */
u_short ea_peerlen; /* Length of peer's name */
enum eap_state_code ea_state;
u_char ea_id; /* Current id */
u_char ea_requests; /* Number of Requests sent/received */
u_char ea_responses; /* Number of Responses */
u_char ea_type; /* One of EAPT_* */
u_int32_t ea_keyflags; /* SRP shared key usage flags */
};
/*
* Complete EAP state for one PPP session.
*/
typedef struct eap_state {
int es_unit; /* Interface unit number */
struct eap_auth es_client; /* Client (authenticatee) data */
struct eap_auth es_server; /* Server (authenticator) data */
int es_savedtime; /* Saved timeout */
int es_rechallenge; /* EAP rechallenge interval */
int es_lwrechallenge; /* SRP lightweight rechallenge inter */
bool es_usepseudo; /* Use SRP Pseudonym if offered one */
int es_usedpseudo; /* Set if we already sent PN */
int es_challen; /* Length of challenge string */
u_char es_challenge[MAX_CHALLENGE_LENGTH];
} eap_state;
/*
* Timeouts.
*/
#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */
#define EAP_DEFTRANSMITS 10 /* max # times to transmit */
#define EAP_DEFREQTIME 20 /* Time to wait for peer request */
#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */
extern eap_state eap_states[];
void eap_authwithpeer __P((int unit, char *localname));
void eap_authpeer __P((int unit, char *localname));
extern struct protent eap_protent;
#ifdef __cplusplus
}
#endif
#endif /* PPP_EAP_H */

View File

@ -17,7 +17,7 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#define RCSID "$Id: lcp.c,v 1.62 2002/09/24 11:35:22 fcusack Exp $"
#define RCSID "$Id: lcp.c,v 1.63 2002/11/02 19:48:12 carlsonj Exp $"
/*
* TODO:
@ -338,6 +338,7 @@ lcp_init(unit)
ao->neg_chap = 1;
ao->chap_mdtype = MDTYPE_ALL;
ao->neg_upap = 1;
ao->neg_eap = 1;
ao->neg_magicnumber = 1;
ao->neg_pcompression = 1;
ao->neg_accompression = 1;
@ -635,13 +636,15 @@ lcp_cilen(f)
#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0)
#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0)
/*
* NB: we only ask for one of CHAP and UPAP, even if we will
* accept either.
* NB: we only ask for one of CHAP, UPAP, or EAP, even if we will
* accept more than one. We prefer EAP first, then CHAP, then
* PAP.
*/
return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) +
LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
LENCICHAP(go->neg_chap) +
LENCISHORT(!go->neg_chap && go->neg_upap) +
LENCISHORT(go->neg_eap) +
LENCICHAP(!go->neg_eap && go->neg_chap) +
LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) +
LENCILQR(go->neg_lqr) +
LENCICBCP(go->neg_cbcp) +
LENCILONG(go->neg_magicnumber) +
@ -715,8 +718,10 @@ lcp_addci(f, ucp, lenp)
ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
go->asyncmap);
ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype);
ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap,
PPP_PAP);
ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
@ -862,8 +867,10 @@ lcp_ackci(f, p, len)
ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
go->asyncmap);
ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype);
ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap,
PPP_PAP);
ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
@ -1026,28 +1033,40 @@ lcp_nakci(f, p, len)
* they are proposing a different protocol, or a different
* hash algorithm for CHAP.
*/
if ((go->neg_chap || go->neg_upap)
if ((go->neg_chap || go->neg_upap || go->neg_eap)
&& len >= CILEN_SHORT
&& p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
cilen = p[1];
len -= cilen;
no.neg_chap = go->neg_chap;
no.neg_upap = go->neg_upap;
no.neg_eap = go->neg_eap;
INCPTR(2, p);
GETSHORT(cishort, p);
if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
/* If we were asking for EAP, then we need to stop that. */
if (go->neg_eap)
try.neg_eap = 0;
/* If we were asking for CHAP, then we need to stop that. */
else if (go->neg_chap)
try.neg_chap = 0;
/*
* If we were asking for CHAP, they obviously don't want to do it.
* If we weren't asking for CHAP, then we were asking for PAP,
* in which case this Nak is bad.
* If we weren't asking for CHAP or EAP, then we were asking for
* PAP, in which case this Nak is bad.
*/
if (!go->neg_chap)
else
goto bad;
try.neg_chap = 0;
} else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
GETCHAR(cichar, p);
if (go->neg_chap) {
/* Stop asking for EAP, if we were. */
if (go->neg_eap) {
try.neg_eap = 0;
/* Try to set up to use their suggestion, if possible */
if (CHAP_CANDIGEST(go->chap_mdtype, cichar))
go->chap_mdtype = CHAP_MDTYPE_D(cichar);
} else if (go->neg_chap) {
/*
* We were asking for our preferred algorithm, they must
* want something different.
@ -1077,11 +1096,21 @@ lcp_nakci(f, p, len)
}
} else {
/*
* If we were asking for EAP, and they're Conf-Naking EAP,
* well, that's just strange. Nobody should do that.
*/
if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap)
dbglog("Unexpected Conf-Nak for EAP");
/*
* We don't recognize what they're suggesting.
* Stop asking for what we were asking for.
*/
if (go->neg_chap)
if (go->neg_eap)
try.neg_eap = 0;
else if (go->neg_chap)
try.neg_chap = 0;
else
try.neg_upap = 0;
@ -1187,7 +1216,8 @@ lcp_nakci(f, p, len)
goto bad;
break;
case CI_AUTHTYPE:
if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap)
if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap ||
go->neg_eap || no.neg_eap)
goto bad;
break;
case CI_MAGICNUMBER:
@ -1313,7 +1343,7 @@ lcp_rejci(f, p, len)
if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
goto bad; \
try.neg = 0; \
try.neg_upap = 0; \
try.neg_eap = try.neg_upap = 0; \
}
#define REJCILONG(opt, neg, val) \
if (go->neg && \
@ -1376,9 +1406,12 @@ lcp_rejci(f, p, len)
REJCISHORT(CI_MRU, neg_mru, go->mru);
REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype);
if (!go->neg_chap) {
REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP);
if (!go->neg_eap) {
REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype);
if (!go->neg_chap) {
REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
}
}
REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
@ -1515,56 +1548,68 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
case CI_AUTHTYPE:
if (cilen < CILEN_SHORT ||
!(ao->neg_upap || ao->neg_chap)) {
!(ao->neg_upap || ao->neg_chap || ao->neg_eap)) {
/*
* Reject the option if we're not willing to authenticate.
*/
dbglog("No auth is possible");
orc = CONFREJ;
break;
}
GETSHORT(cishort, p);
/*
* Authtype must be PAP or CHAP.
* Authtype must be PAP, CHAP, or EAP.
*
* Note: if both ao->neg_upap and ao->neg_chap are set,
* and the peer sends a Configure-Request with two
* authenticate-protocol requests, one for CHAP and one
* for UPAP, then we will reject the second request.
* Whether we end up doing CHAP or UPAP depends then on
* Note: if more than one of ao->neg_upap, ao->neg_chap, and
* ao->neg_eap are set, and the peer sends a Configure-Request
* with two or more authenticate-protocol requests, then we will
* reject the second request.
* Whether we end up doing CHAP, UPAP, or EAP depends then on
* the ordering of the CIs in the peer's Configure-Request.
*/
if (cishort == PPP_PAP) {
if (ho->neg_chap || /* we've already accepted CHAP */
/* we've already accepted CHAP or EAP */
if (ho->neg_chap || ho->neg_eap ||
cilen != CILEN_SHORT) {
LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
orc = CONFREJ;
break;
}
if (!ao->neg_upap) { /* we don't want to do PAP */
orc = CONFNAK; /* NAK it and suggest CHAP */
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_CHAP, nakp);
PUTSHORT(PPP_CHAP, nakp);
PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
orc = CONFNAK; /* NAK it and suggest CHAP or EAP */
if (ao->neg_eap) {
PUTCHAR(CILEN_SHORT, nakp);
PUTSHORT(PPP_EAP, nakp);
} else {
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_CHAP, nakp);
PUTSHORT(PPP_CHAP, nakp);
PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
}
break;
}
ho->neg_upap = 1;
break;
}
if (cishort == PPP_CHAP) {
if (ho->neg_upap || /* we've already accepted PAP */
/* we've already accepted PAP or EAP */
if (ho->neg_upap || ho->neg_eap ||
cilen != CILEN_CHAP) {
LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
orc = CONFREJ;
break;
}
if (!ao->neg_chap) { /* we don't want to do CHAP */
orc = CONFNAK; /* NAK it and suggest PAP */
orc = CONFNAK; /* NAK it and suggest EAP or PAP */
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_SHORT, nakp);
PUTSHORT(PPP_PAP, nakp);
if (ao->neg_eap) {
PUTSHORT(PPP_EAP, nakp);
} else {
PUTSHORT(PPP_PAP, nakp);
}
break;
}
GETCHAR(cichar, p); /* get digest type */
@ -1584,15 +1629,42 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
ho->neg_chap = 1;
break;
}
if (cishort == PPP_EAP) {
/* we've already accepted CHAP or PAP */
if (ho->neg_chap || ho->neg_upap || cilen != CILEN_SHORT) {
LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting..."));
orc = CONFREJ;
break;
}
if (!ao->neg_eap) { /* we don't want to do EAP */
orc = CONFNAK; /* NAK it and suggest CHAP or PAP */
PUTCHAR(CI_AUTHTYPE, nakp);
if (ao->neg_chap) {
PUTCHAR(CILEN_CHAP, nakp);
PUTSHORT(PPP_CHAP, nakp);
PUTCHAR(ao->chap_mdtype, nakp);
} else {
PUTCHAR(CILEN_SHORT, nakp);
PUTSHORT(PPP_PAP, nakp);
}
break;
}
ho->neg_eap = 1;
break;
}
/*
* We don't recognize the protocol they're asking for.
* Nak it with something we're willing to do.
* (At this point we know ao->neg_upap || ao->neg_chap.)
* (At this point we know ao->neg_upap || ao->neg_chap ||
* ao->neg_eap.)
*/
orc = CONFNAK;
PUTCHAR(CI_AUTHTYPE, nakp);
if (ao->neg_chap) {
if (ao->neg_eap) {
PUTCHAR(CILEN_SHORT, nakp);
PUTSHORT(PPP_EAP, nakp);
} else if (ao->neg_chap) {
PUTCHAR(CILEN_CHAP, nakp);
PUTSHORT(PPP_CHAP, nakp);
PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
@ -1956,6 +2028,9 @@ lcp_printpkt(p, plen, printer, arg)
}
}
break;
case PPP_EAP:
printer(arg, "eap");
break;
default:
printer(arg, "0x%x", cishort);
}

View File

@ -16,7 +16,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: lcp.h,v 1.17 2002/03/01 14:39:18 dfs Exp $
* $Id: lcp.h,v 1.18 2002/11/02 19:48:12 carlsonj Exp $
*/
/*
@ -54,6 +54,7 @@ typedef struct lcp_options {
bool neg_asyncmap; /* Negotiate the async map? */
bool neg_upap; /* Ask for UPAP authentication? */
bool neg_chap; /* Ask for CHAP authentication? */
bool neg_eap; /* Ask for EAP authentication? */
bool neg_magicnumber; /* Ask for magic number? */
bool neg_pcompression; /* HDLC Protocol Field Compression? */
bool neg_accompression; /* HDLC Address/Control Field Compression? */

View File

@ -17,7 +17,7 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#define RCSID "$Id: main.c,v 1.118 2002/10/27 12:19:58 fcusack Exp $"
#define RCSID "$Id: main.c,v 1.119 2002/11/02 19:48:12 carlsonj Exp $"
#include <stdio.h>
#include <ctype.h>
@ -52,6 +52,7 @@
#endif
#include "upap.h"
#include "chap.h"
#include "eap.h"
#include "ccp.h"
#include "ecp.h"
#include "pathnames.h"
@ -229,6 +230,7 @@ struct protent *protocols[] = {
#ifdef AT_CHANGE
&atcp_protent,
#endif
&eap_protent,
NULL
};
@ -990,7 +992,7 @@ get_input()
* Toss all non-LCP packets unless LCP is OPEN.
*/
if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
MAINDEBUG(("get_input: Received non-LCP packet when LCP not open."));
dbglog("Discarded non-LCP packet when LCP not open");
return;
}
@ -1000,9 +1002,10 @@ get_input()
*/
if (phase <= PHASE_AUTHENTICATE
&& !(protocol == PPP_LCP || protocol == PPP_LQR
|| protocol == PPP_PAP || protocol == PPP_CHAP)) {
MAINDEBUG(("get_input: discarding proto 0x%x in phase %d",
protocol, phase));
|| protocol == PPP_PAP || protocol == PPP_CHAP ||
protocol == PPP_EAP)) {
dbglog("discarding proto 0x%x in phase %d",
protocol, phase);
return;
}

View File

@ -1,7 +1,7 @@
/*
* define path names
*
* $Id: pathnames.h,v 1.14 2001/03/08 05:15:37 paulus Exp $
* $Id: pathnames.h,v 1.15 2002/11/02 19:48:13 carlsonj Exp $
*/
#ifdef HAVE_PATHS_H
@ -20,6 +20,7 @@
#define _PATH_UPAPFILE _ROOT_PATH "/etc/ppp/pap-secrets"
#define _PATH_CHAPFILE _ROOT_PATH "/etc/ppp/chap-secrets"
#define _PATH_SRPFILE _ROOT_PATH "/etc/ppp/srp-secrets"
#define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options"
#define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up"
#define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down"
@ -31,6 +32,7 @@
#define _PATH_RESOLV _ROOT_PATH "/etc/ppp/resolv.conf"
#define _PATH_USEROPT ".ppprc"
#define _PATH_PSEUDONYM ".ppp_pseudonym"
#ifdef INET6
#define _PATH_IPV6UP _ROOT_PATH "/etc/ppp/ipv6-up"

185
pppd/pppcrypt.c Normal file
View File

@ -0,0 +1,185 @@
/*
* pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1
*
* Extracted from chap_ms.c by James Carlson.
*
* Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
* http://www.strataware.com/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Eric Rosenquist. The name of the author may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <errno.h>
#include "pppd.h"
#include "pppcrypt.h"
static u_char
Get7Bits(input, startBit)
u_char *input;
int startBit;
{
unsigned int word;
word = (unsigned)input[startBit / 8] << 8;
word |= (unsigned)input[startBit / 8 + 1];
word >>= 15 - (startBit % 8 + 7);
return word & 0xFE;
}
static void
MakeKey(key, des_key)
u_char *key; /* IN 56 bit DES key missing parity bits */
u_char *des_key; /* OUT 64 bit DES key with parity bits added */
{
des_key[0] = Get7Bits(key, 0);
des_key[1] = Get7Bits(key, 7);
des_key[2] = Get7Bits(key, 14);
des_key[3] = Get7Bits(key, 21);
des_key[4] = Get7Bits(key, 28);
des_key[5] = Get7Bits(key, 35);
des_key[6] = Get7Bits(key, 42);
des_key[7] = Get7Bits(key, 49);
#ifndef USE_CRYPT
des_set_odd_parity((des_cblock *)des_key);
#endif
}
#ifdef USE_CRYPT
/*
* in == 8-byte string (expanded version of the 56-bit key)
* out == 64-byte string where each byte is either 1 or 0
* Note that the low-order "bit" is always ignored by by setkey()
*/
static void
Expand(in, out)
u_char *in;
u_char *out;
{
int j, c;
int i;
for (i = 0; i < 64; in++){
c = *in;
for (j = 7; j >= 0; j--)
*out++ = (c >> j) & 01;
i += 8;
}
}
/* The inverse of Expand
*/
static void
Collapse(in, out)
u_char *in;
u_char *out;
{
int j;
int i;
unsigned int c;
for (i = 0; i < 64; i += 8, out++) {
c = 0;
for (j = 7; j >= 0; j--, in++)
c |= *in << j;
*out = c & 0xff;
}
}
bool
DesSetkey(key)
u_char *key;
{
u_char des_key[8];
u_char crypt_key[66];
MakeKey(key, des_key);
Expand(des_key, crypt_key);
errno = 0;
setkey((const char *)crypt_key);
if (errno != 0)
return (0);
return (1);
}
bool
DesEncrypt(clear, cipher)
u_char *clear; /* IN 8 octets */
u_char *cipher; /* OUT 8 octets */
{
u_char des_input[66];
Expand(clear, des_input);
errno = 0;
encrypt((char *)des_input, 0);
if (errno != 0)
return (0);
Collapse(des_input, cipher);
return (1);
}
bool
DesDecrypt(cipher, clear)
u_char *cipher; /* IN 8 octets */
u_char *clear; /* OUT 8 octets */
{
u_char des_input[66];
Expand(cipher, des_input);
errno = 0;
encrypt((char *)des_input, 1);
if (errno != 0)
return (0);
Collapse(des_input, clear);
return (1);
}
#else /* USE_CRYPT */
static des_key_schedule key_schedule;
bool
DesSetkey(key)
u_char *key;
{
des_cblock des_key;
MakeKey(key, des_key);
des_set_key(&des_key, key_schedule);
return (1);
}
bool
DesEncrypt(clear, key, cipher)
u_char *clear; /* IN 8 octets */
u_char *cipher; /* OUT 8 octets */
{
des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher,
key_schedule, 1);
return (1);
}
bool
DesDecrypt(cipher, clear)
u_char *cipher; /* IN 8 octets */
u_char *clear; /* OUT 8 octets */
{
des_ecb_encrypt((des_cblock *)cipher, (des_cblock *)clear,
key_schedule, 0);
return (1);
}
#endif /* USE_CRYPT */

40
pppd/pppcrypt.h Normal file
View File

@ -0,0 +1,40 @@
/*
* pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1
*
* Extracted from chap_ms.c by James Carlson.
*
* Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
* http://www.strataware.com/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Eric Rosenquist. The name of the author may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef PPPCRYPT_H
#define PPPCRYPT_H
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#ifndef USE_CRYPT
#include <des.h>
#endif
extern bool DesSetkey __P((u_char *));
extern bool DesEncrypt __P((u_char *, u_char *));
extern bool DesDecrypt __P((u_char *, u_char *));
#endif /* PPPCRYPT_H */

View File

@ -1,5 +1,5 @@
.\" manual page [] for pppd 2.4
.\" $Id: pppd.8,v 1.66 2002/10/10 05:47:34 fcusack Exp $
.\" $Id: pppd.8,v 1.67 2002/11/02 19:48:13 carlsonj Exp $
.\" SH section heading
.\" SS subsection heading
.\" LP paragraph
@ -331,6 +331,28 @@ the MAC type, the value may also be the name of an ethernet or similar
network interface. This option is currently only available under
Linux.
.TP
.B eap-interval \fIn
If this option is given and pppd authenticates the peer with EAP
(i.e., is the server), pppd will restart EAP authentication every
\fIn\fR seconds. For EAP SRP-SHA1, see also the \fBsrp-interval\fR
option, which enables lightweight rechallenge.
.TP
.B eap-max-rreq \fIn
Set the maximum number of EAP Requests to which pppd will respond (as
a client) without hearing EAP Success or Failure. (Default is 20.)
.TP
.B eap-max-sreq \fIn
Set the maximum number of EAP Requests that pppd will issue (as a
server) while attempting authentication. (Default is 10.)
.TP
.B eap-restart \fIn
Set the retransmit timeout for EAP Requests when acting as a server
(authenticator). (Default is 3 seconds.)
.TP
.B eap-timeout \fIn
Set the maximum time to wait for the peer to send an EAP Request when
acting as a client (authenticatee). (Default is 20 seconds.)
.TP
.B hide-password
When logging the contents of PAP packets, this option causes pppd to
exclude the password string from the log. This is the default.
@ -885,6 +907,10 @@ peer using MS-CHAP.
With this option, pppd will not agree to authenticate itself to the
peer using MS-CHAPv2.
.TP
.B refuse-eap
With this option, pppd will not agree to authenticate itself to the
peer using EAP.
.TP
.B refuse-pap
With this option, pppd will not agree to authenticate itself to the
peer using PAP.
@ -915,6 +941,10 @@ Handshake Authentication Protocol] authentication.
Require the peer to authenticate itself using MS-CHAPv2 [Microsft Challenge
Handshake Authentication Protocol, Version 2] authentication.
.TP
.B require-eap
Require the peer to authenticate itself using EAP [Extensible
Authentication Protocol] authentication.
.TP
.B require-pap
Require the peer to authenticate itself using PAP [Password
Authentication Protocol] authentication.
@ -928,6 +958,27 @@ With this option, pppd will not transmit LCP packets to initiate a
connection until a valid LCP packet is received from the peer (as for
the `passive' option with ancient versions of pppd).
.TP
.B srp-interval \fIn
If this parameter is given and pppd uses EAP SRP-SHA1 to authenticate
the peer (i.e., is the server), then pppd will use the optional
lightweight SRP rechallenge mechanism at intervals of \fIn\fR
seconds. This option is faster than \fBeap-interval\fR
reauthentication because it uses a hash-based mechanism and does not
derive a new session key.
.TP
.B srp-pn-secret \fIstring
Set the long-term pseudonym-generating secret for the server. This
value is optional and if set, needs to be known at the server
(authenticator) side only, and should be different for each server (or
poll of identical servers). It is used along with the current date to
generate a key to encrypt and decrypt the client's identity contained
in the pseudonym.
.TP
.B srp-use-pseudonym
When operating as an EAP SRP-SHA1 client, attempt to use the pseudonym
stored in ~/.ppp_psuedonym first as the identity, and save in this
file any pseudonym offered by the peer during authentication.
.TP
.B sync
Use synchronous HDLC serial encoding instead of asynchronous.
The device used by pppd with this option must have sync support.
@ -1044,15 +1095,18 @@ knows that secret. Very often, the names used for authentication
correspond to the internet hostnames of the peers, but this is not
essential.
.LP
At present, pppd supports two authentication protocols: the Password
Authentication Protocol (PAP) and the Challenge Handshake
Authentication Protocol (CHAP). PAP involves the client sending its
name and a cleartext password to the server to authenticate itself.
In contrast, the server initiates the CHAP authentication exchange by
sending a challenge to the client (the challenge packet includes the
server's name). The client must respond with a response which
includes its name plus a hash value derived from the shared secret and
the challenge, in order to prove that it knows the secret.
At present, pppd supports three authentication protocols: the Password
Authentication Protocol (PAP), Challenge Handshake Authentication
Protocol (CHAP), and Extensible Authentication Protocol (EAP). PAP
involves the client sending its name and a cleartext password to the
server to authenticate itself. In contrast, the server initiates the
CHAP authentication exchange by sending a challenge to the client (the
challenge packet includes the server's name). The client must respond
with a response which includes its name plus a hash value derived from
the shared secret and the challenge, in order to prove that it knows
the secret. EAP supports CHAP-style authentication, and also includes
the SRP-SHA1 mechanism, which is resistant to dictionary-based attacks
and does not require a cleartext password on the server side.
.LP
The PPP protocol, being symmetrical, allows both peers to require the
other to authenticate itself. In that case, two separate and
@ -1066,9 +1120,10 @@ pppd will not agree to authenticate itself with a particular protocol
if it has no secrets which could be used to do so.
.LP
Pppd stores secrets for use in authentication in secrets
files (/etc/ppp/pap-secrets for PAP, /etc/ppp/chap-secrets for
CHAP/MS-CHAP/MS-CHAPv2).
Both secrets files have the same format. The secrets files can
files (/etc/ppp/pap-secrets for PAP, /etc/ppp/chap-secrets for CHAP,
MS-CHAP, MS-CHAPv2, and EAP MD5-Challenge, and /etc/ppp/srp-secrets
for EAP SRP-SHA1).
All secrets files have the same format. The secrets files can
contain secrets for pppd to use in authenticating itself to other
systems, as well as secrets for pppd to use when authenticating other
systems to itself.
@ -1113,7 +1168,9 @@ field and the name of the local system in the second field. The
name of the local system defaults to the hostname, with the domain
name appended if the \fIdomain\fR option is used. This default can be
overridden with the \fIname\fR option, except when the
\fIusehostname\fR option is used.
\fIusehostname\fR option is used. (For EAP SRP-SHA1, see the
srp-entry(8) utility for generating proper validator entries to be
used in the "secret" field.)
.LP
When pppd is choosing a secret to use in authenticating itself to the
peer, it first determines what name it is going to use to identify
@ -1122,14 +1179,14 @@ itself to the peer. This name can be specified by the user with the
the name of the local system, determined as described in the previous
paragraph. Then pppd looks for a secret with this name in the first
field and the peer's name in the second field. Pppd will know the
name of the peer if CHAP authentication is being used, because the
peer will have sent it in the challenge packet. However, if PAP is being
used, pppd will have to determine the peer's name from the options
specified by the user. The user can specify the peer's name directly
with the \fIremotename\fR option. Otherwise, if the remote IP address
was specified by a name (rather than in numeric form), that name will
be used as the peer's name. Failing that, pppd will use the null
string as the peer's name.
name of the peer if CHAP or EAP authentication is being used, because
the peer will have sent it in the challenge packet. However, if PAP
is being used, pppd will have to determine the peer's name from the
options specified by the user. The user can specify the peer's name
directly with the \fIremotename\fR option. Otherwise, if the remote
IP address was specified by a name (rather than in numeric form), that
name will be used as the peer's name. Failing that, pppd will use the
null string as the peer's name.
.LP
When authenticating the peer with PAP, the supplied password is first
compared with the secret from the secrets file. If the password
@ -1295,16 +1352,18 @@ pppd proxyarp
.LP
To allow a user to use the PPP facilities, you need to allocate an IP
address for that user's machine and create an entry in
/etc/ppp/pap-secrets or /etc/ppp/chap-secrets (depending on which
authentication method the PPP implementation on the user's machine
supports), so that the user's
machine can authenticate itself. For example, if Joe has a machine
called "joespc" which is to be allowed to dial in to the machine
called "server" and use the IP address joespc.my.net, you would add an
entry like this to /etc/ppp/pap-secrets or /etc/ppp/chap-secrets:
/etc/ppp/pap-secrets, /etc/ppp/chap-secrets, or /etc/ppp/srp-secrets
(depending on which authentication method the PPP implementation on
the user's machine supports), so that the user's machine can
authenticate itself. For example, if Joe has a machine called
"joespc" that is to be allowed to dial in to the machine called
"server" and use the IP address joespc.my.net, you would add an entry
like this to /etc/ppp/pap-secrets or /etc/ppp/chap-secrets:
.IP
joespc server "joe's secret" joespc.my.net
.LP
(See srp-entry(8) for a means to generate the server's entry when
SRP-SHA1 is in use.)
Alternatively, you can create a username called (for example) "ppp",
whose login shell is pppd and whose home directory is /etc/ppp.
Options to be used when pppd is run this way can be put in
@ -1329,7 +1388,7 @@ and debug messages, you will need to edit your /etc/syslog.conf file
to direct the messages to the desired output device or file.
.LP
The \fIdebug\fR option causes the contents of all control packets sent
or received to be logged, that is, all LCP, PAP, CHAP or IPCP packets.
or received to be logged, that is, all LCP, PAP, CHAP, EAP, or IPCP packets.
This can be useful if the PPP negotiation does not succeed or if
authentication fails.
If debugging is enabled at compile time, the \fIdebug\fR option also
@ -1561,6 +1620,16 @@ As for /etc/ppp/pap-secrets, this file should be owned by root and not
readable or writable by any other user. Pppd will log a warning if
this is not the case.
.TP
.B /etc/ppp/srp-secrets
Names, secrets, and IP addresses for EAP authentication. As for
/etc/ppp/pap-secrets, this file should be owned by root and not
readable or writable by any other user. Pppd will log a warning if
this is not the case.
.TP
.B ~/.ppp_pseudonym
Saved client-side SRP-SHA1 pseudonym. See the \fIsrp-use-pseudonym\fR
option for details.
.TP
.B /etc/ppp/options
System default options for pppd, read before user default options or
command-line options.
@ -1613,10 +1682,25 @@ Simpson, W.A.
.I PPP in HDLC-like Framing.
July 1994.
.TP
.B RFC2284
Blunk, L.; Vollbrecht, J.,
.I PPP Extensible Authentication Protocol (EAP).
March 1998.
.TP
.B RFC2472
Haskin, D.
.I IP Version 6 over PPP
December 1998.
.TP
.B RFC2945
Wu, T.,
.I The SRP Authentication and Key Exchange System
September 2000.
.TP
.B draft-ietf-pppext-eap-srp-03.txt
Carlson, J.; et al.,
.I EAP SRP-SHA1 Authentication Protocol.
July 2001.
.SH NOTES
The following signals have the specified effect when sent to pppd.
.TP

View File

@ -16,7 +16,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: pppd.h,v 1.76 2002/10/27 12:30:54 fcusack Exp $
* $Id: pppd.h,v 1.77 2002/11/02 19:48:13 carlsonj Exp $
*/
/*
@ -317,15 +317,18 @@ extern bool ms_lanman; /* Use LanMan password instead of NT */
#define PAP_PEER 0x2
#define CHAP_WITHPEER 0x4
#define CHAP_PEER 0x8
#define EAP_WITHPEER 0x10
#define EAP_PEER 0x20
/* Values for auth_done only */
#define CHAP_MD5_WITHPEER 0x10
#define CHAP_MD5_PEER 0x20
#define CHAP_MD5_WITHPEER 0x40
#define CHAP_MD5_PEER 0x80
#ifdef CHAPMS
#define CHAP_MS_SHIFT 6 /* LSB position for MS auths */
#define CHAP_MS_WITHPEER 0x40
#define CHAP_MS_PEER 0x80
#define CHAP_MS2_WITHPEER 0x100
#define CHAP_MS2_PEER 0x200
#define CHAP_MS_SHIFT 8 /* LSB position for MS auths */
#define CHAP_MS_WITHPEER 0x100
#define CHAP_MS_PEER 0x200
#define CHAP_MS2_WITHPEER 0x400
#define CHAP_MS2_PEER 0x800
#endif
extern char *current_option; /* the name of the option being parsed */
@ -514,6 +517,8 @@ int check_passwd __P((int, char *, int, char *, int, char **));
/* Check peer-supplied username/password */
int get_secret __P((int, char *, char *, char *, int *, int));
/* get "secret" for chap */
int get_srp_secret __P((int unit, char *client, char *server, char *secret,
int am_server));
int auth_ip_addr __P((int, u_int32_t));
/* check if IP address is authorized */
int auth_number __P((void)); /* check if remote number is authorized */
@ -719,6 +724,7 @@ extern void (*snoop_send_hook) __P((unsigned char *p, int len));
#define BCOPY(s, d, l) memcpy(d, s, l)
#define BZERO(s, n) memset(s, 0, n)
#define BCMP(s1, s2, l) memcmp(s1, s2, l)
#define PRINTMSG(m, l) { info("Remote message: %0.*v", l, m); }

View File

@ -1,5 +1,11 @@
/* sha1.h */
/* If OpenSSL is in use, then use that version of SHA-1 */
#ifdef OPENSSL
#include <t_sha.h>
#define __SHA1_INCLUDE_
#endif
#ifndef __SHA1_INCLUDE_
typedef struct {
@ -8,11 +14,17 @@ typedef struct {
unsigned char buffer[64];
} SHA1_CTX;
#define SHA1_SIGNATURE_SIZE 20
extern void SHA1_Init(SHA1_CTX *);
extern void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int);
extern void SHA1_Final(unsigned char[SHA1_SIGNATURE_SIZE], SHA1_CTX *);
#define __SHA1_INCLUDE_
#endif /* __SHA1_INCLUDE_ */
#ifndef SHA1_SIGNATURE_SIZE
#ifdef SHA_DIGESTSIZE
#define SHA1_SIGNATURE_SIZE SHA_DIGESTSIZE
#else
#define SHA1_SIGNATURE_SIZE 20
#endif
#endif

83
pppd/srp-entry.8 Normal file
View File

@ -0,0 +1,83 @@
.\" manual page [] for srp-entry
.\" $Id: srp-entry.8,v 1.1 2002/11/02 19:48:13 carlsonj Exp $
.\" SH section heading
.\" SS subsection heading
.\" LP paragraph
.\" IP indented paragraph
.\" TP hanging label
.TH SRP-ENTRY 8
.SH NAME
srp-entry \- Generate a SRP-SHA1 Server Entry
.SH SYNOPSIS
.B srp-entry
[
.I -i index
] [
.I clientname
]
.SH DESCRIPTION
.LP
This utility generates an entry suitable for use in the
/etc/ppp/srp-secrets file on a PPP EAP SRP-SHA1 authenticator
("server"). This file has the same basic layout as the other pppd(8)
authentication files, /etc/ppp/pap-secrets and /etc/ppp/chap-secrets.
Thus, the entry generated has at least four main fields separated by
spaces. The first field is the authenticatee ("client") name. The
second is the server name. The third is the secret. The fourth is
the allowed (or assigned) IP address for the client, and defaults to
"*". Additional fields can contain additional IP addresses or pppd
options; see pppd(8) for details.
.LP
The third field has three subfields, separated by colons. The first
subfield is the index of the modulus and generator from SRP's
/etc/tpasswd.conf. The special value 0 is used to represent the
well-known modulus and generator specified in the EAP SRP-SHA1 draft.
The second subfield is the password validator. The third is the
password salt. These latter two values are encoded in base64 notation.
.SH OPTIONS
.TP
.I -i <index>
Specifies the modulus/generator index in /etc/tpasswd.conf. In order
to use this option, you will need to run the "tconf" utility from the
SRP package to generate local entries for this file. Note that if
these values are not known to the client, the client will be forced to
run time-consuming safety tests on the values used. For this reason,
using the well-known values is recommended.
.TP
.I <clientname>
Specifies the client name. The password validator is a hashed
combination of the client's name and password, and both are required.
If the client name is not supplied on the command line, srp-entry will
prompt for the client name first.
.SH FILES
.TP
.B /etc/ppp/srp-secrets
Usernames, passwords and IP addresses for SRP authentication. This
file should be owned by root and not readable or writable by any other
user. Pppd will log a warning if this is not the case. Note that
srp-entry does not write to this file. The user is responsible for
copying the output of srp-entry into this file.
.TP
.B /etc/tpasswd.conf
Indexed copies of tested modulus/generator combinations; part of the
SRP package.
.SH SEE ALSO
.TP
pppd(8)
.TP
.B RFC2284
Blunk, L., Vollbrecht, J.,
.I PPP Extensible Authentication Protocol (EAP).
March 1998.
.TP
.B draft-ietf-pppext-eap-srp-03.txt
Carlson, J., et al.,
.I EAP SRP-SHA1 Authentication Protocol.
July 2001.
.TP
.B RFC2945
Wu, T.,
.I The SRP Authentication and Key Exchange System
September 2000.
.SH AUTHOR
James Carlson (james.d.carlson@sun.com)

190
pppd/srp-entry.c Normal file
View File

@ -0,0 +1,190 @@
/*
* Utility program for generating entries in /etc/ppp/srp-secrets
*
* Copyright (c) 2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* Non-exclusive rights to redistribute, modify, translate, and use
* this software in source and binary forms, in whole or in part, is
* hereby granted, provided that the above copyright notice is
* duplicated in any source form, and that neither the name of the
* copyright holder nor the author is used to endorse or promote
* products derived from this software.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Original version by James Carlson
*
* Usage:
* srp-entry [-i index] [clientname]
*
* Index, if supplied, is the modulus/generator index from
* /etc/tpasswd.conf. If not supplied, then the last (highest
* numbered) entry from that file is used. If the file doesn't exist,
* then the default "well known" EAP SRP-SHA1 modulus/generator is
* used.
*
* The default modulus/generator can be requested as index 0.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <t_pwd.h>
#ifndef SOL2
#define getpassphrase getpass
#endif
#define HAS_SPACE 1
#define HAS_DQUOTE 2
#define HAS_SQUOTE 4
#define HAS_BACKSLASH 8
static const u_char wkmodulus[] = {
0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
};
static const char *myname;
static void
usage(void)
{
(void) fprintf(stderr, "Usage:\n\t%s [-i index] [clientname]\n",
myname);
exit(1);
}
int
main(int argc, char **argv)
{
struct t_conf *tc;
struct t_confent *tcent, mytce;
struct t_pw pwval;
char *name;
char pname[256];
char *pass1, *pass2;
int flags, idx;
char *cp;
char delimit;
char strbuf[MAXB64PARAMLEN];
char saltbuf[MAXB64SALTLEN];
if ((myname = *argv) == NULL)
myname = "srp-entry";
else
argv++;
idx = -1;
if (*argv != NULL && strcmp(*argv, "-i") == 0) {
if (*++argv == NULL)
usage();
idx = atoi(*argv++);
}
tcent = NULL;
if (idx != 0 && (tc = t_openconf(NULL)) != NULL) {
if (idx == -1)
tcent = t_getconflast(tc);
else
tcent = t_getconfbyindex(tc, idx);
}
if (idx <= 0 && tcent == NULL) {
mytce.index = 0;
mytce.modulus.data = (u_char *)wkmodulus;
mytce.modulus.len = sizeof (wkmodulus);
mytce.generator.data = (u_char *)"\002";
mytce.generator.len = 1;
tcent = &mytce;
}
if (tcent == NULL) {
(void) fprintf(stderr, "SRP modulus/generator %d not found\n",
idx);
exit(1);
}
if ((name = *argv) == NULL) {
(void) printf("Client name: ");
if (fgets(pname, sizeof (pname), stdin) == NULL)
exit(1);
if ((cp = strchr(pname, '\n')) != NULL)
*cp = '\0';
name = pname;
}
for (;;) {
if ((pass1 = getpassphrase("Pass phrase: ")) == NULL)
exit(1);
pass1 = strdup(pass1);
if ((pass2 = getpassphrase("Re-enter phrase: ")) == NULL)
exit(1);
if (strcmp(pass1, pass2) == 0)
break;
free(pass1);
(void) printf("Phrases don't match; try again.\n");
}
memset(&pwval, 0, sizeof (pwval));
t_makepwent(&pwval, name, pass1, NULL, tcent);
flags = 0;
for (cp = name; *cp != '\0'; cp++)
if (isspace(*cp))
flags |= HAS_SPACE;
else if (*cp == '"')
flags |= HAS_DQUOTE;
else if (*cp == '\'')
flags |= HAS_SQUOTE;
else if (*cp == '\\')
flags |= HAS_BACKSLASH;
delimit = flags == 0 ? '\0' : (flags & HAS_DQUOTE) ? '\'' : '"';
if (delimit != '\0')
(void) putchar(delimit);
for (cp = name; *cp != '\0'; cp++) {
if (*cp == delimit || *cp == '\\')
(void) putchar('\\');
(void) putchar(*cp);
}
if (delimit != '\0')
(void) putchar(delimit);
(void) printf(" * %d:%s:%s *\n",
pwval.pebuf.index, t_tob64(strbuf,
(char *)pwval.pebuf.password.data, pwval.pebuf.password.len),
t_tob64(saltbuf, (char *)pwval.pebuf.salt.data,
pwval.pebuf.salt.len));
return 0;
}