initial check in

This commit is contained in:
hipp 1997-03-07 15:57:03 +00:00
parent 4c3ccfc893
commit 8f5ca2eb2b
46 changed files with 23340 additions and 0 deletions

92
ipppd/Makefile Normal file
View File

@ -0,0 +1,92 @@
#
# pppd makefile for Linux
# $Id: Makefile,v 1.1 1997/03/07 16:01:00 hipp Exp $
#
# These are set from the main Makefile
# BINDIR = /sbin/
# MANDIR = /usr/man/
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
ipxcp.c auth.c options.c sys-linux.c cbcp.c
HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h \
ipxcp.h cbcp.h
MANPAGES = pppd.8
PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
auth.o options.o sys-linux.o cbcp.o ipxcp.o
all: ipppd
#
# include dependancies if present and backup if as a header file
ifeq (.depend,$(wildcard .depend))
include .depend
HEADERS := $(HEADERS) .depend
endif
# CC = gcc
DEBUG_FLAGS = -DDEBUGALL
# USE_MSCHAP = 1
# HAS_SHADOW = 1
COMPILE_FLAGS = -D_linux_=1 -DHAVE_PATHS_H -Wall -Dlint # -DDEBUGALL
COPTS = -O2 -fomit-frame-pointer -m486 # -g
VER = 2.2.0
LIBS = -lbsd
CFLAGS= $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS)
SOURCE= RELNOTES Makefile.linux $(PPPDSRCS) $(HEADERS) $(MANPAGES)
ifdef USE_MSCHAP
PPPDSRCS += md4.c chap_ms.c
PPPDOBJS += md4.o chap_ms.o
HEADERS += md4.h ms_chap.h
CFLAGS += -DUSE_MSCHAP
LIBS += -ldes
endif
ifdef USE_MS_DNS
CFLAGS += -DUSE_MS_DNS=1
endif
ifdef HAS_SHADOW
CFLAGS += -DHAS_SHADOW
LIBS += -lcrypt
PPPDOBJS += isexpired.o
PPPDSRCS += isexpired.c
endif
install: ipppd
mkdir -p $(BINDIR) $(MANDIR)
install -s -c -m 555 -o root ipppd $(BINDIR)/ipppd
install -c -m 555 -o root ipppd.8 $(MANDIR)/man8
ipppd: $(PPPDOBJS)
$(CC) $(CFLAGS) -o ipppd $(PPPDOBJS) $(LIBS)
pppd.tar: $(SOURCE)
tar -cvf pppd.tar $(SOURCE)
pppd.tar.gz: pppd.tar
gzip pppd.tar
clean:
rm -f $(PPPDOBJS) ipppd *~ #* core
depend:
$(CPP) -M $(CFLAGS) $(PPPDSRCS) >.depend
#
# These disable warnings because some people complain about the
# warnings which do not cause harm.
#
main.o: main.c
$(CC) $(CFLAGS) -o main.o -c main.c
auth.o: auth.c
$(CC) $(CFLAGS) -o auth.o -c auth.c
options.o: options.c
$(CC) $(CFLAGS) -o options.o -c options.c

92
ipppd/Makefile.linux Normal file
View File

@ -0,0 +1,92 @@
#
# pppd makefile for Linux
# $Id: Makefile.linux,v 1.1 1997/03/07 16:01:01 hipp Exp $
#
# These are set from the main Makefile
# BINDIR = /sbin/
# MANDIR = /usr/man/
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
ipxcp.c auth.c options.c sys-linux.c cbcp.c
HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h \
ipxcp.h cbcp.h
MANPAGES = pppd.8
PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
auth.o options.o sys-linux.o cbcp.o ipxcp.o
all: ipppd
#
# include dependancies if present and backup if as a header file
ifeq (.depend,$(wildcard .depend))
include .depend
HEADERS := $(HEADERS) .depend
endif
# CC = gcc
DEBUG_FLAGS = -DDEBUGALL
# USE_MSCHAP = 1
# HAS_SHADOW = 1
COMPILE_FLAGS = -D_linux_=1 -DHAVE_PATHS_H -Wall -Dlint # -DDEBUGALL
COPTS = -O2 -fomit-frame-pointer -m486 # -g
VER = 2.2.0
LIBS = -lbsd
CFLAGS= $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS)
SOURCE= RELNOTES Makefile.linux $(PPPDSRCS) $(HEADERS) $(MANPAGES)
ifdef USE_MSCHAP
PPPDSRCS += md4.c chap_ms.c
PPPDOBJS += md4.o chap_ms.o
HEADERS += md4.h ms_chap.h
CFLAGS += -DUSE_MSCHAP
LIBS += -ldes
endif
ifdef USE_MS_DNS
CFLAGS += -DUSE_MS_DNS=1
endif
ifdef HAS_SHADOW
CFLAGS += -DHAS_SHADOW
LIBS += -lcrypt
PPPDOBJS += isexpired.o
PPPDSRCS += isexpired.c
endif
install: ipppd
mkdir -p $(BINDIR) $(MANDIR)
install -s -c -m 555 -o root ipppd $(BINDIR)/ipppd
install -c -m 555 -o root ipppd.8 $(MANDIR)/man8
ipppd: $(PPPDOBJS)
$(CC) $(CFLAGS) -o ipppd $(PPPDOBJS) $(LIBS)
pppd.tar: $(SOURCE)
tar -cvf pppd.tar $(SOURCE)
pppd.tar.gz: pppd.tar
gzip pppd.tar
clean:
rm -f $(PPPDOBJS) ipppd *~ #* core
depend:
$(CPP) -M $(CFLAGS) $(PPPDSRCS) >.depend
#
# These disable warnings because some people complain about the
# warnings which do not cause harm.
#
main.o: main.c
$(CC) $(CFLAGS) -o main.o -c main.c
auth.o: auth.c
$(CC) $(CFLAGS) -o auth.o -c auth.c
options.o: options.c
$(CC) $(CFLAGS) -o options.o -c options.c

89
ipppd/NOTES.IPPPD Normal file
View File

@ -0,0 +1,89 @@
ipppd, based on pppd 2.2.0g with a few changes from 2.3
============================================================
copyright (c) 1995,1996,1997 of all changes by Michael Hipp
ATTENTION .. NEW NEW NEW NEW NEW
********************************
You need at least the 2.0.29 base patch because of a
new ioctl!!
changed default pathname for options to:
/etc/ppp/ioptions
pidfilename changed to:
ipppd.pid
removed checking of ~/.ppprc file ('options from user' feature)
------------------------------------------------------------
I added a few new options:
- 'useifip' will get (if not set to 0.0.0.0) the IP address
for the negotiation from the attached network-interface.
(also: ipppd will try to negotiate 'pointopoint' IP as remote IP)
interface address -> local IP
pointopoint address -> remote IP
- '+mp' enables MPPP negotiation
- 'useifmtu': a not so important option .. better use
the 'mtu' option ..
- from the ppp-2.3 package I took the 'noccp' option.
(-ccp is the same). Necessary for a few
netblazers on the remote side.
- 'usefirstip' gets the remote address from the first entry in
the auth file (if there is an IP address entry). This address
should be a full IP address not an address from a masked area.
Ipppd calls 'gethostbyname()' and negotiates the result.
IP from auth file will overwrite the remote address gotten
from the interface.
'usefirstip' is UNTESTED!
- 'callback type[,message]' enables the callback feature
also UNTESTED!
e.g: 'callback 0' -> simple callback (info via auth. etc.)
'callback 3,12346' -> us E.164 (tel) number 123456 for callback
- IPX and MS_DNS are now compiled into the binary without additional option
Applied Hartwig Felgers MS-DNS (re)patch for this
The ipppd can handle multiple devices. This is necessary to
link several connections together to one bundle.
Also, you only start the ipppd once. It now opens the devices
and waits for connections.
If you (or the remote side) closes the connection the ipppd
reopens the device automatically. (the device .. not the link
to the remote)
So you shouldn't kill the ipppd to close a link. Instead, trigger
a hangup on the netdevice layer.
(with isdn4linux: isdnctrl hangup <device>')
I applied the mschap80 patches (see README.mschap80), but this
is untested.
I also started to apply the CBCP patches .. not yet finished.
May not work!
I disabled the facility to configure the daemon via
the /dev/ppp/ioptions.<devname> file. It's not necessary.
Use the 'file' option or the command line for individual
configuration.
Better don't set the permissions of the programm to
'setuid to root on execution'. Call the daemon as root instead.
No common user must call the daemon!
---------------------------------------------------------------------
1. Corrections for shadow support. This means that the isexpired routine
has been removed, the references to pw_crypt have been changed to use
crypt, etc.
You must, repeat, MUST, have the libcrypt library if you now wish to use
shadow passwords. The library is available with the crypt library.
2. The corrections for the IPXCP routing code.
3. The addition of a /etc/ppp/auth-up and /etc/ppp/auth-down program. This
is used to aid implementations which rely upon the in-band authentication
protocols.
5. The corrections which broken implementations of authentication
protocol to cause pppd to loop. I am only aware of the Tumpet winsock
stack which caused this condition.

26
ipppd/README Normal file
View File

@ -0,0 +1,26 @@
Introduction.
*************
The Point-to-Point Protocol (PPP) provides a standard way to transmit
datagrams over a serial link, as well as a standard way for the
machines at either end of the link (the `peers') to negotiate various
optional characteristics of the link. Using PPP, a serial link can be
used to transmit Internet Protocol (IP) datagrams, allowing TCP/IP
connections between the peers. PPP is defined in several RFC (Request
For Comments) documents, in particular RFCs 1661, 1662, 1332 and 1334.
Other RFCs describe standard ways to transmit datagrams from other
network protocols (e.g., DECnet, OSI, Appletalk), but this package
only supports IP.
This implementation consists of two parts:
- kernel code, which implements an interface between the isdn4linux
subsystem and the networking code. The interface also forwards
control frames to the ippp-device
- The PPP daemon (ipppd), which negotiates with the peer to establish
the link and configures the ippp network interface. Ipppd includes
support for authentication, so you can control which other systems
may make a PPP connection and what IP addresses they may use.

1515
ipppd/README.cbcp.ORIG Normal file

File diff suppressed because it is too large Load Diff

1033
ipppd/README.linux.ORIG Normal file

File diff suppressed because it is too large Load Diff

847
ipppd/README.mschap80.ORIG Normal file
View File

@ -0,0 +1,847 @@
PPP Client Support for Microsoft's CHAP-80
==========================================
Eric Rosenquist rosenqui@strataware.com
INTRODUCTION
Microsoft has introduced an extension to the Challenge/Handshake
Authentication Protocol (CHAP) which eliminates the need for them to have
access to cleartext passwords. The details of the Microsoft extensions can
be found in the document:
<ftp://ftp.microsoft.com/developr/rfc/chapexts.txt>
In short, MS-CHAP is identified as <auth chap 80> since the hex value of 80
is used to designate Microsoft's scheme. Standard PPP CHAP uses a value of
5. If you enable PPP debugging with the "debug" option and see something
like the following in your logs, the remote server is requesting MS-CHAP:
rcvd [LCP ConfReq id=0x2 <asyncmap 0x0> <auth chap 80> <magic 0x46a3>]
^^^^^^^^^^^^
The standard PPP implementation will indicate its lack of support for
MS-CHAP by NAKing it:
lcp_reqci: rcvd AUTHTYPE
(c223)
(NAK)
Windows NT Server systems are often configured to "Accept only Microsoft
Authentication" to enhance security. Up until now, that meant that you
couldn't use this version of PPPD to connect to such a system. I've
managed to get a client-only implementation of MS-CHAP working; it will
authenticate itself to another system using MS-CHAP, but if you're using
PPPD as a dial-in server, you won't be able to use MS-CHAP to authenticate
the clients. This would not be a lot of extra work given that the
framework is in place, but I didn't need it myself so I didn't implement
it.
BUILDING THE PPPD
MS-CHAP uses a combination of MD4 hashing and DES encryption for
authentication. You'll need to get Eric Young's DES library in order to
use my MS-CHAP extensions. You can find it in:
<ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/>
I used libdes-3.06, but hopefully anything newer than that will work also.
Get the library, build and test it on your system, and install it somewhere
(typically /usr/local/lib and /usr/local/include).
You should now be ready to (re)compile the PPPD. Go to the ppp-X.Y/pppd
directory and make sure the Makefile contains "-DUSE_MSCHAP" in the
COMPILE_FLAGS macro, and that the LIBS macro contains "-ldes". Depending
on your system and where the DES library was installed, you may also need
to alter the include and library paths used by your compiler.
Do a "make clean" and then a "make" to rebuild the PPPD. Assuming all goes
well, install the new PPPD and move on to the CONFIGURATION section.
CONFIGURATION
If you've never used PPPD with CHAP before, read the man page (type "man
pppd") and read the description in there. Basically, you need to edit the
"chap-secrets" file typically named /etc/ppp/chap-secrets. This should
contain the following two lines for each system with which you use CHAP
(with no leading blanks):
RemoteHost Account Secret
Account RemoteHost Secret
Note that you need both lines and that item 1 and 2 are swapped in the
second line. I'm not sure why you need it twice, but it works and I didn't
have time to look into it further. The "RemoteHost" is a somewhat
arbitrary name for the remote Windows NT system you're dialing. It doesn't
have to match the NT system's name, but it *does* have to match what you
use with the "remotename" parameter. The "Account" is the Windows NT
account name you have been told to use when dialing, and the "Secret" is
the password for that account. For example, if your service provider calls
their machine "DialupNT" and tells you your account and password are
"customer47" and "foobar", add the following to your chap-secrets file:
DialupNT customer47 foobar
customer47 DialupNT foobar
The only other thing you need to do for MS-CHAP (compared to normal CHAP)
is to always use the "remotename" option, either on the command line or in
your "options" file (see the pppd man page for details). In the case of
the above example, you would need to use the following command line:
pppd name customer47 remotename DialupNT <other options>
or add:
name customer47
remotename DialupNT
to your PPPD "options" file.
The "remotename" option is required for MS-CHAP since Microsoft PPP servers
don't send their system name in the CHAP challenge packet.
TROUBLESHOOTING
Assuming that everything else has been configured correctly for PPP and
CHAP, the MS-CHAP-specific problems you're likely to encounter are mostly
related to your Windows NT account and its settings. A Microsoft server
returns error codes in its CHAP response. The following are extracted from
Microsoft's "chapexts.txt" file referenced above:
646 ERROR_RESTRICTED_LOGON_HOURS
647 ERROR_ACCT_DISABLED
648 ERROR_PASSWD_EXPIRED
649 ERROR_NO_DIALIN_PERMISSION
691 ERROR_AUTHENTICATION_FAILURE
709 ERROR_CHANGING_PASSWORD
You'll see these in your pppd log as a line similar to:
Remote message: E=649 R=0
The "E=" is the error number from the table above, and the "R=" flag
indicates whether the error is transient and the client should retry. If
you consistently get error 691, then either you're using the wrong account
name/password, or the DES library or MD4 hashing (in md4.c) aren't working
properly. Verify your account name and password (use a Windows NT or
Windows 95 system to dial-in if you have one available). If that checks
out, test the DES library with the "destest" program included with the DES
library. If DES checks out, the md4.c routines are probably failing
(system byte ordering may be a problem) or my code is screwing up. I've
only got access to a Linux system, so you're on your own for anything else.
I can generate an MD4 test program if necessary in order to verify proper
MD4 operation.
STILL TO DO
A site using only MS-CHAP to authenticate has no need to store cleartext
passwords in the "chap-secrets" file. A utility that spits out the ASCII
hex MD4 hash of a given password would be nice, and would allow that hash
to be used in chap-secrets in place of the password. The code to do this
could quite easily be lifted from chap_ms.c (you have to convert the
password to Unicode before hashing it). The chap_ms.c file would also have
to be changed to recognize a password hash (16 binary bytes == 32 ASCII hex
characters) and skip the hashing stage.
A server implementation would allow MS-CHAP to be used with Windows NT and
Windows 95 clients for enhanced security. Some new command-line options
would be required, as would code to generate the Challenge packet and
verify the response. Most of the helper functions are in place, so this
shouldn't be too hard for someone to add.
These are the differences to the origial 2.2.0f distribution package. You
must use the patch utility to apply these patches before the code may be
built.
diff --unified --recursive --new-file ppp-2.2.0f.orig/pppd/Makefile.linux ppp-2.2.0f/pppd/Makefile.linux
--- ppp-2.2.0f.orig/pppd/Makefile.linux Fri Apr 12 06:27:12 1996
+++ ppp-2.2.0f/pppd/Makefile.linux Fri Apr 12 06:25:01 1996
@@ -4,8 +4,8 @@
#
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
- ipxcp.c auth.c options.c sys-linux.c
-HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h \
+ ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c
+HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h chap_ms.h md4.h \
ipxcp.h
MANPAGES = pppd.8
PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
@@ -29,6 +29,13 @@
CFLAGS= $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS)
SOURCE= RELNOTES Makefile.linux $(PPPDSRCS) $(HEADERS) $(MANPAGES)
+
+ifdef USE_MSCHAP
+PPPDSRCS += md4.c chap_ms.c
+PPPDOBJS += md4.o chap_ms.o
+CFLAGS += -DUSE_MSCHAP
+LIBS += -ldes
+endif
ifdef USE_MS_DNS
CFLAGS += -DUSE_MS_DNS=1
diff --unified --recursive --new-file ppp-2.2.0f.orig/pppd/chap.c ppp-2.2.0f/pppd/chap.c
--- ppp-2.2.0f.orig/pppd/chap.c Fri Apr 12 06:10:30 1996
+++ ppp-2.2.0f/pppd/chap.c Fri Apr 12 06:25:01 1996
@@ -34,6 +34,9 @@
#include "pppd.h"
#include "chap.h"
+#ifdef USE_MSCHAP
+#include "chap_ms.h"
+#endif /* USE_MSCHAP */
#include "md5.h"
chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
@@ -370,8 +373,17 @@
BCOPY(inp, rhostname, len);
rhostname[len] = '\000';
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field: %s",
- rhostname));
+ CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field: '%s'",
+ rhostname));
+
+#ifdef USE_MSCHAP
+ /* Microsoft doesn't send their name back in the PPP packet */
+ if (!rhostname[0] && cstate->resp_type == CHAP_MICROSOFT) {
+ extern char remote_name[];
+ strcpy(rhostname, remote_name);
+ CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name", rhostname));
+ }
+#endif /* USE_MSCHAP */
/* get secret for authenticating ourselves with the specified host */
if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
@@ -391,7 +403,7 @@
/* generate MD based on negotiated type */
switch (cstate->resp_type) {
- case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
+ case CHAP_DIGEST_MD5:
MD5Init(&mdContext);
MD5Update(&mdContext, &cstate->resp_id, 1);
MD5Update(&mdContext, secret, secret_len);
@@ -400,6 +412,12 @@
BCOPY(mdContext.digest, cstate->response, MD5_SIGNATURE_SIZE);
cstate->resp_length = MD5_SIGNATURE_SIZE;
break;
+
+#ifdef USE_MSCHAP
+ case CHAP_MICROSOFT:
+ ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
+ break;
+#endif /* USE_MSCHAP */
default:
CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->resp_type));
diff --unified --recursive --new-file ppp-2.2.0f.orig/pppd/chap.h ppp-2.2.0f/pppd/chap.h
--- ppp-2.2.0f.orig/pppd/chap.h Fri Apr 12 06:10:30 1996
+++ ppp-2.2.0f/pppd/chap.h Fri Apr 12 06:25:01 1996
@@ -39,9 +39,10 @@
/*
* Challenge lengths (for challenges we send) and other limits.
*/
+
#define MIN_CHALLENGE_LENGTH 32
#define MAX_CHALLENGE_LENGTH 64
-#define MAX_RESPONSE_LENGTH 16 /* sufficient for MD5 */
+#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 and MSCHAP */
/*
* Each interface is described by a chap structure.
diff --unified --recursive --new-file ppp-2.2.0f.orig/pppd/chap_ms.c ppp-2.2.0f/pppd/chap_ms.c
--- ppp-2.2.0f.orig/pppd/chap_ms.c Wed Dec 31 16:00:00 1969
+++ ppp-2.2.0f/pppd/chap_ms.c Fri Apr 12 06:25:02 1996
@@ -0,0 +1,179 @@
+/*
+ * chap_ms.c - Microsoft MS-CHAP compatible implementation.
+ *
+ * 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.
+ */
+
+#ifdef USE_MSCHAP
+#ifndef lint
+static char rcsid[] = "$Id: README.mschap80.ORIG,v 1.1 1997/03/07 16:01:05 hipp Exp $";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <syslog.h>
+
+#include "pppd.h"
+#include "chap.h"
+#include "chap_ms.h"
+#include "md4.h"
+
+#include <des.h>
+
+typedef struct {
+ u_char LANManResp[24];
+ u_char NTResp[24];
+ u_char UseNT; /* If 1, ignore the LANMan response field */
+} MS_ChapResponse;
+#define MS_CHAP_RESPONSE_LEN 49 /* Don't rely on sizeof(MS_ChapResponse) in case of struct padding */
+
+
+static void DesEncrypt __P((u_char *, u_char *, u_char *));
+static void MakeKey __P((u_char *, u_char *));
+
+static void
+ChallengeResponse(challenge, pwHash, response)
+ u_char *challenge; /* IN 8 octets */
+ u_char *pwHash; /* IN 16 octets */
+ u_char *response; /* OUT 24 octets */
+{
+ char ZPasswordHash[21];
+
+ BZERO(ZPasswordHash, sizeof(ZPasswordHash));
+ BCOPY(pwHash, ZPasswordHash, 16);
+
+#if 0
+ log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash");
+#endif
+
+ DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
+ DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
+ DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
+
+#if 0
+ log_packet(response, 24, "ChallengeResponse - response");
+#endif
+}
+
+
+static void
+DesEncrypt(clear, key, cipher)
+ u_char *clear; /* IN 8 octets */
+ u_char *key; /* IN 7 octets */
+ u_char *cipher; /* OUT 8 octets */
+{
+ 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 : %02X%02X%02X%02X%02X%02X%02X%02X",
+ clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
+#endif
+
+ des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
+
+#if 0
+ CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X",
+ cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
+#endif
+}
+
+
+static u_char Get7Bits(input, startBit)
+ 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;
+}
+
+
+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);
+
+ des_set_odd_parity((des_cblock *)des_key);
+
+#if 0
+ CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X",
+ key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
+ CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X",
+ des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
+#endif
+}
+#endif /* USE_MSCHAP */
+
+void
+ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len)
+ chap_state *cstate;
+ char *rchallenge;
+ int rchallenge_len;
+ char *secret;
+ int secret_len;
+{
+#ifdef USE_MSCHAP
+ int i;
+ MDstruct md4Context;
+ MS_ChapResponse response;
+ u_char unicodePassword[MAX_NT_PASSWORD * 2];
+
+#if 0
+ CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
+#endif
+
+ BZERO(&response, sizeof(response));
+
+ /* Initialize the Unicode version of the secret (== password). */
+ /* This implicitly supports 8-bit ISO8859/1 characters. */
+ BZERO(unicodePassword, sizeof(unicodePassword));
+ for (i = 0; i < secret_len; i++)
+ unicodePassword[i * 2] = (u_char)secret[i];
+
+ MDbegin(&md4Context);
+ MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */
+ MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */
+
+ ChallengeResponse(rchallenge, (char *)md4Context.buffer, response.NTResp);
+
+ response.UseNT = 1;
+
+ BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
+ cstate->resp_length = MS_CHAP_RESPONSE_LEN;
+#endif /* USE_MSCHAP */
+}
diff --unified --recursive --new-file ppp-2.2.0f.orig/pppd/chap_ms.h ppp-2.2.0f/pppd/chap_ms.h
--- ppp-2.2.0f.orig/pppd/chap_ms.h Wed Dec 31 16:00:00 1969
+++ ppp-2.2.0f/pppd/chap_ms.h Fri Apr 12 06:25:02 1996
@@ -0,0 +1,32 @@
+/*
+ * chap.h - Cryptographic Handshake Authentication Protocol definitions.
+ *
+ * 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.
+ *
+ * $Id: README.mschap80.ORIG,v 1.1 1997/03/07 16:01:05 hipp Exp $
+ */
+
+#ifndef __CHAPMS_INCLUDE__
+
+#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */
+
+void ChapMS __P((chap_state *, char *, int, char *, int));
+
+#define __CHAPMS_INCLUDE__
+#endif /* __CHAPMS_INCLUDE__ */
diff --unified --recursive --new-file ppp-2.2.0f.orig/pppd/lcp.c ppp-2.2.0f/pppd/lcp.c
--- ppp-2.2.0f.orig/pppd/lcp.c Fri Apr 12 06:10:31 1996
+++ ppp-2.2.0f/pppd/lcp.c Fri Apr 12 06:25:02 1996
@@ -1263,7 +1263,11 @@
break;
}
GETCHAR(cichar, p); /* get digest type*/
+#ifndef USE_MSCHAP
if (cichar != ao->chap_mdtype) {
+#else
+ if (cichar != ao->chap_mdtype && cichar != CHAP_MICROSOFT) {
+#endif /* USE_MSCHAP */
orc = CONFNAK;
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_CHAP, nakp);
diff --unified --recursive --new-file ppp-2.2.0f.orig/pppd/md4.c ppp-2.2.0f/pppd/md4.c
--- ppp-2.2.0f.orig/pppd/md4.c Wed Dec 31 16:00:00 1969
+++ ppp-2.2.0f/pppd/md4.c Fri Apr 12 06:10:31 1996
@@ -0,0 +1,295 @@
+/*
+** ********************************************************************
+** md4.c -- Implementation of MD4 Message Digest Algorithm **
+** Updated: 2/16/90 by Ronald L. Rivest **
+** (C) 1990 RSA Data Security, Inc. **
+** ********************************************************************
+*/
+
+/*
+** To use MD4:
+** -- Include md4.h in your program
+** -- Declare an MDstruct MD to hold the state of the digest
+** computation.
+** -- Initialize MD using MDbegin(&MD)
+** -- For each full block (64 bytes) X you wish to process, call
+** MDupdate(&MD,X,512)
+** (512 is the number of bits in a full block.)
+** -- For the last block (less than 64 bytes) you wish to process,
+** MDupdate(&MD,X,n)
+** where n is the number of bits in the partial block. A partial
+** block terminates the computation, so every MD computation
+** should terminate by processing a partial block, even if it
+** has n = 0.
+** -- The message digest is available in MD.buffer[0] ...
+** MD.buffer[3]. (Least-significant byte of each word
+** should be output first.)
+** -- You can print out the digest using MDprint(&MD)
+*/
+
+/* Implementation notes:
+** This implementation assumes that ints are 32-bit quantities.
+** If the machine stores the least-significant byte of an int in the
+** least-addressed byte (e.g., VAX and 8086), then LOWBYTEFIRST
+** should be set to TRUE. Otherwise (e.g., SUNS), LOWBYTEFIRST
+** should be set to FALSE. Note that on machines with LOWBYTEFIRST
+** FALSE the routine MDupdate modifies has a side-effect on its input
+** array (the order of bytes in each word are reversed). If this is
+** undesired a call to MDreverse(X) can reverse the bytes of X back
+** into order after each call to MDupdate.
+**
+** NOTE: LOWBYTEFIRST removed by Eric Rosenquist in favour of run-time
+** detection to simplify build process.
+*/
+
+#define TRUE 1
+#define FALSE 0
+
+/* Compile-time includes
+*/
+#include <stdio.h>
+#include "md4.h"
+#include "pppd.h"
+
+/* Compile-time declarations of MD4 "magic constants".
+*/
+#define I0 0x67452301 /* Initial values for MD buffer */
+#define I1 0xefcdab89
+#define I2 0x98badcfe
+#define I3 0x10325476
+#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
+#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
+/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
+** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
+** Table 2, page 660.
+*/
+
+#define fs1 3 /* round 1 shift amounts */
+#define fs2 7
+#define fs3 11
+#define fs4 19
+#define gs1 3 /* round 2 shift amounts */
+#define gs2 5
+#define gs3 9
+#define gs4 13
+#define hs1 3 /* round 3 shift amounts */
+#define hs2 9
+#define hs3 11
+#define hs4 15
+
+/* Compile-time macro declarations for MD4.
+** Note: The "rot" operator uses the variable "tmp".
+** It assumes tmp is declared as unsigned int, so that the >>
+** operator will shift in zeros rather than extending the sign bit.
+*/
+#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
+#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
+#define h(X,Y,Z) (X^Y^Z)
+#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
+#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
+#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
+#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
+
+/* MDprint(MDp)
+** Print message digest buffer MDp as 32 hexadecimal digits.
+** Order is from low-order byte of buffer[0] to high-order byte of
+** buffer[3].
+** Each byte is printed with high-order hexadecimal digit first.
+** This is a user-callable routine.
+*/
+void
+MDprint(MDp)
+MDptr MDp;
+{ int i,j;
+for (i=0;i<4;i++)
+ for (j=0;j<32;j=j+8)
+ printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
+}
+
+/* MDbegin(MDp)
+** Initialize message digest buffer MDp.
+** This is a user-callable routine.
+*/
+void
+MDbegin(MDp)
+MDptr MDp;
+{ int i;
+MDp->buffer[0] = I0;
+MDp->buffer[1] = I1;
+MDp->buffer[2] = I2;
+MDp->buffer[3] = I3;
+for (i=0;i<8;i++) MDp->count[i] = 0;
+MDp->done = 0;
+}
+
+/* MDreverse(X)
+** Reverse the byte-ordering of every int in X.
+** Assumes X is an array of 16 ints.
+** The macro revx reverses the byte-ordering of the next word of X.
+*/
+#define revx { t = (*X << 16) | (*X >> 16); \
+ *X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); }
+MDreverse(X)
+unsigned int *X;
+{ register unsigned int t;
+revx; revx; revx; revx; revx; revx; revx; revx;
+revx; revx; revx; revx; revx; revx; revx; revx;
+}
+
+/* MDblock(MDp,X)
+** Update message digest buffer MDp->buffer using 16-word data block X.
+** Assumes all 16 words of X are full of data.
+** Does not update MDp->count.
+** This routine is not user-callable.
+*/
+static void
+MDblock(MDp,X)
+MDptr MDp;
+unsigned int *X;
+{
+register unsigned int tmp, A, B, C, D;
+static int low_byte_first = -1;
+
+if (low_byte_first == -1) {
+ low_byte_first = (htons((unsigned short int)1) != 1);
+}
+
+if (low_byte_first == 0) {
+ MDreverse(X);
+}
+
+A = MDp->buffer[0];
+B = MDp->buffer[1];
+C = MDp->buffer[2];
+D = MDp->buffer[3];
+/* Update the message digest buffer */
+ff(A , B , C , D , 0 , fs1); /* Round 1 */
+ff(D , A , B , C , 1 , fs2);
+ff(C , D , A , B , 2 , fs3);
+ff(B , C , D , A , 3 , fs4);
+ff(A , B , C , D , 4 , fs1);
+ff(D , A , B , C , 5 , fs2);
+ff(C , D , A , B , 6 , fs3);
+ff(B , C , D , A , 7 , fs4);
+ff(A , B , C , D , 8 , fs1);
+ff(D , A , B , C , 9 , fs2);
+ff(C , D , A , B , 10 , fs3);
+ff(B , C , D , A , 11 , fs4);
+ff(A , B , C , D , 12 , fs1);
+ff(D , A , B , C , 13 , fs2);
+ff(C , D , A , B , 14 , fs3);
+ff(B , C , D , A , 15 , fs4);
+gg(A , B , C , D , 0 , gs1); /* Round 2 */
+gg(D , A , B , C , 4 , gs2);
+gg(C , D , A , B , 8 , gs3);
+gg(B , C , D , A , 12 , gs4);
+gg(A , B , C , D , 1 , gs1);
+gg(D , A , B , C , 5 , gs2);
+gg(C , D , A , B , 9 , gs3);
+gg(B , C , D , A , 13 , gs4);
+gg(A , B , C , D , 2 , gs1);
+gg(D , A , B , C , 6 , gs2);
+gg(C , D , A , B , 10 , gs3);
+gg(B , C , D , A , 14 , gs4);
+gg(A , B , C , D , 3 , gs1);
+gg(D , A , B , C , 7 , gs2);
+gg(C , D , A , B , 11 , gs3);
+gg(B , C , D , A , 15 , gs4);
+hh(A , B , C , D , 0 , hs1); /* Round 3 */
+hh(D , A , B , C , 8 , hs2);
+hh(C , D , A , B , 4 , hs3);
+hh(B , C , D , A , 12 , hs4);
+hh(A , B , C , D , 2 , hs1);
+hh(D , A , B , C , 10 , hs2);
+hh(C , D , A , B , 6 , hs3);
+hh(B , C , D , A , 14 , hs4);
+hh(A , B , C , D , 1 , hs1);
+hh(D , A , B , C , 9 , hs2);
+hh(C , D , A , B , 5 , hs3);
+hh(B , C , D , A , 13 , hs4);
+hh(A , B , C , D , 3 , hs1);
+hh(D , A , B , C , 11 , hs2);
+hh(C , D , A , B , 7 , hs3);
+hh(B , C , D , A , 15 , hs4);
+MDp->buffer[0] += A;
+MDp->buffer[1] += B;
+MDp->buffer[2] += C;
+MDp->buffer[3] += D;
+}
+
+/* MDupdate(MDp,X,count)
+** Input: MDp -- an MDptr
+** X -- a pointer to an array of unsigned characters.
+** count -- the number of bits of X to use.
+** (if not a multiple of 8, uses high bits of last byte.)
+** Update MDp using the number of bits of X given by count.
+** This is the basic input routine for an MD4 user.
+** The routine completes the MD computation when count < 512, so
+** every MD computation should end with one call to MDupdate with a
+** count less than 512. A call with count 0 will be ignored if the
+** MD has already been terminated (done != 0), so an extra call with
+** count 0 can be given as a "courtesy close" to force termination
+** if desired.
+*/
+void
+MDupdate(MDp,X,count)
+MDptr MDp;
+unsigned char *X;
+unsigned int count;
+{ unsigned int i, tmp, bit, byte, mask;
+unsigned char XX[64];
+unsigned char *p;
+/* return with no error if this is a courtesy close with count
+** zero and MDp->done is true.
+*/
+if (count == 0 && MDp->done) return;
+/* check to see if MD is already done and report error */
+if (MDp->done)
+ { printf("\nError: MDupdate MD already done."); return; }
+/* Add count to MDp->count */
+tmp = count;
+p = MDp->count;
+while (tmp)
+ { tmp += *p;
+ *p++ = tmp;
+ tmp = tmp >> 8;
+ }
+/* Process data */
+if (count == 512)
+ { /* Full block of data to handle */
+ MDblock(MDp,(unsigned int *)X);
+ }
+else if (count > 512) /* Check for count too large */
+ { printf("\nError: MDupdate called with illegal count value %d."
+ ,count);
+ return;
+ }
+else /* partial block -- must be last block so finish up */
+ { /* Find out how many bytes and residual bits there are */
+ byte = count >> 3;
+ bit = count & 7;
+ /* Copy X into XX since we need to modify it */
+ for (i=0;i<=byte;i++) XX[i] = X[i];
+ for (i=byte+1;i<64;i++) XX[i] = 0;
+ /* Add padding '1' bit and low-order zeros in last byte */
+ mask = 1 << (7 - bit);
+ XX[byte] = (XX[byte] | mask) & ~( mask - 1);
+ /* If room for bit count, finish up with this block */
+ if (byte <= 55)
+ { for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ else /* need to do two blocks to finish up */
+ { MDblock(MDp,(unsigned int *)XX);
+ for (i=0;i<56;i++) XX[i] = 0;
+ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ /* Set flag saying we're done with MD computation */
+ MDp->done = 1;
+ }
+}
+
+/*
+** End of md4.c
+****************************(cut)***********************************/
diff --unified --recursive --new-file ppp-2.2.0f.orig/pppd/md4.h ppp-2.2.0f/pppd/md4.h
--- ppp-2.2.0f.orig/pppd/md4.h Wed Dec 31 16:00:00 1969
+++ ppp-2.2.0f/pppd/md4.h Fri Apr 12 06:10:31 1996
@@ -0,0 +1,51 @@
+/*
+** ********************************************************************
+** md4.h -- Header file for implementation of **
+** MD4 Message Digest Algorithm **
+** Updated: 2/13/90 by Ronald L. Rivest **
+** (C) 1990 RSA Data Security, Inc. **
+** ********************************************************************
+*/
+
+/* MDstruct is the data structure for a message digest computation.
+*/
+typedef struct {
+unsigned int buffer[4]; /* Holds 4-word result of MD computation */
+unsigned char count[8]; /* Number of bits processed so far */
+unsigned int done; /* Nonzero means MD computation finished */
+} MDstruct, *MDptr;
+
+/* MDbegin(MD)
+** Input: MD -- an MDptr
+** Initialize the MDstruct prepatory to doing a message digest
+** computation.
+*/
+extern void MDbegin();
+
+/* MDupdate(MD,X,count)
+** Input: MD -- an MDptr
+** X -- a pointer to an array of unsigned characters.
+** count -- the number of bits of X to use (an unsigned int).
+** Updates MD using the first "count" bits of X.
+** The array pointed to by X is not modified.
+** If count is not a multiple of 8, MDupdate uses high bits of
+** last byte.
+** This is the basic input routine for a user.
+** The routine terminates the MD computation when count < 512, so
+** every MD computation should end with one call to MDupdate with a
+** count less than 512. Zero is OK for a count.
+*/
+extern void MDupdate();
+
+/* MDprint(MD)
+** Input: MD -- an MDptr
+** Prints message digest buffer MD as 32 hexadecimal digits.
+** Order is from low-order byte of buffer[0] to high-order byte
+** of buffer[3].
+** Each byte is printed with high-order hexadecimal digit first.
+*/
+extern void MDprint();
+
+/*
+** End of md4.h
+****************************(cut)***********************************/

17
ipppd/TODO.4.MP Normal file
View File

@ -0,0 +1,17 @@
TODO to support full MP handling with multiple connections.
----
some of the following values must be changed to fields:
(put them into the link structures)
xmit_accm
(kill_link, is global)
lcp_echos_pending
lcp_echo_fails
lcp_echo_number
lcp_echo_interval
idle_time_limit
lcp_echo_timer_running
hungup
(baud_rate isn't necessary)

1176
ipppd/auth.c Normal file

File diff suppressed because it is too large Load Diff

419
ipppd/cbcp.c Normal file
View File

@ -0,0 +1,419 @@
/*
* cbcp - Call Back Configuration Protocol.
*
* Copyright (c) 1995 Pedro Roque Marques
* 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 Pedro Roque Marques. 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.
*/
#define PPP_CBCP 0xc029 /* Callback Control Protocol */
#ifndef lint
static char rcsid[] = "$Id: cbcp.c,v 1.1 1997/03/07 16:01:09 hipp Exp $";
#endif
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <syslog.h>
#include "pppd.h"
#include "cbcp.h"
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
/*
* Protocol entry points.
*/
static void cbcp_init __P((int unit));
static void cbcp_open __P((int unit));
static void cbcp_close __P((int unit,char *));
static void cbcp_lowerup __P((int unit));
static void cbcp_lowerdown __P((int unit));
static void cbcp_input __P((int unit, u_char *pkt, int len));
static void cbcp_protrej __P((int unit));
static int cbcp_printpkt __P((u_char *pkt, int len,
void (*printer) __P((void *, char *, ...)),
void *arg));
struct protent cbcp_protent = {
PPP_CBCP,
cbcp_init,
cbcp_input,
cbcp_protrej,
cbcp_lowerup,
cbcp_lowerdown,
cbcp_open,
cbcp_close,
cbcp_printpkt,
NULL,
0,
"CBCP",
NULL,
NULL,
NULL
};
cbcp_state cbcp[NUM_PPP];
/* internal prototypes */
void cbcp_recvreq(cbcp_state *us, char *pckt, int len);
void cbcp_resp(cbcp_state *us);
void cbcp_up(cbcp_state *us);
void cbcp_recvack(cbcp_state *us, char *pckt, int len);
void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len);
/* init state */
static void cbcp_init(int cbcp_unit)
{
cbcp_state *us;
us = &cbcp[cbcp_unit];
memset(us, 0, sizeof(cbcp_state));
us->us_unit = -1;
us->us_type |= (1 << CB_CONF_NO);
us->us_type |= (1 << CB_CONF_USER);
}
/* lower layer is up */
static void cbcp_lowerup(int cbcp_unit)
{
#if 0
cbcp_state *us = &cbcp[cbcp_unit];
#endif
syslog(LOG_DEBUG, "cbcp_lowerup");
}
static void cbcp_lowerdown(int cbcp_unit)
{
syslog(LOG_DEBUG, "cbcp_lowerdown");
}
static void cbcp_open(int cbcp_unit)
{
syslog(LOG_DEBUG, "cbcp_open");
}
static void cbcp_close(int cbcp_unit,char *reason)
{
syslog(LOG_DEBUG, "cbcp_close: %s",reason);
}
/* process an incomming packet */
static void cbcp_input(int cbcp_unit, u_char *inpacket, int pktlen)
{
u_char *inp;
u_char code, id;
u_short len;
cbcp_state *us = &cbcp[cbcp_unit];
inp = inpacket;
if (pktlen < CBCP_MINLEN) {
syslog(LOG_ERR, "CBCP packet is too small");
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
#if 0
if (len > pktlen) {
syslog(LOG_ERR, "CBCP packet: invalid length");
return;
}
#endif
len -= CBCP_MINLEN;
switch(code) {
case CBCP_REQ:
us->us_id = id;
cbcp_recvreq(us, inp, len);
break;
case CBCP_RESP:
syslog(LOG_DEBUG, "CBCP_RESP received");
break;
case CBCP_ACK:
if (id != us->us_id)
syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d",
us->us_id, id);
cbcp_recvack(us, inp, len);
break;
default:
break;
}
}
/* protocol was rejected by foe */
static void cbcp_protrej(int cbcp_unit)
{
}
char *cbcp_codenames[] = {"Request", "Response", "Ack"};
char *cbcp_optionnames[] = { "NoCallback",
"UserDefined",
"AdminDefined",
"List"};
/* pretty print a packet */
static int cbcp_printpkt(u_char *p, int plen,
void (*printer) __P((void *, char *, ...)),
void *arg)
{
int code, opt, id, len, olen, delay;
u_char *pstart;
if (plen < HEADERLEN)
return 0;
pstart = p;
GETCHAR(code, p);
GETCHAR(id, p);
GETSHORT(len, p);
if (len < HEADERLEN || len > plen)
return 0;
if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
printer(arg, " %s", cbcp_codenames[code-1]);
else
printer(arg, " code=0x%x", code);
printer(arg, " id=0x%x", id);
len -= HEADERLEN;
switch (code) {
case CBCP_REQ:
case CBCP_RESP:
case CBCP_ACK:
while(len >= 2) {
GETCHAR(opt, p);
GETCHAR(olen, p);
if (olen < 2 || olen > len) {
break;
}
printer(arg, " <");
len -= olen;
if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
printer(arg, " %s", cbcp_optionnames[opt-1]);
else
printer(arg, " option=0x%x", opt);
if (olen > 2) {
GETCHAR(delay, p);
printer(arg, " delay = %d", delay);
}
if (olen > 3) {
int addrt;
char str[256];
GETCHAR(addrt, p);
memcpy(str, p, olen - 4);
str[olen - 4] = 0;
printer(arg, " number = %s", str);
}
printer(arg, ">");
break;
}
default:
break;
}
for (; len > 0; --len) {
GETCHAR(code, p);
printer(arg, " %.2x", code);
}
return p - pstart;
}
/* received CBCP request */
void cbcp_recvreq(cbcp_state *us, char *pckt, int pcktlen)
{
u_char type, opt_len, delay, addr_type;
char address[256];
int len = pcktlen;
address[0] = 0;
while (len) {
syslog(LOG_DEBUG, "length: %d", len);
GETCHAR(type, pckt);
GETCHAR(opt_len, pckt);
if (opt_len > 2)
GETCHAR(delay, pckt);
us->us_allowed |= (1 << type);
switch(type) {
case CB_CONF_NO:
syslog(LOG_DEBUG, "no callback allowed");
break;
case CB_CONF_USER:
syslog(LOG_DEBUG, "user callback allowed");
if (opt_len > 4) {
GETCHAR(addr_type, pckt);
memcpy(address, pckt, opt_len - 4);
address[opt_len - 4] = 0;
if (address[0])
syslog(LOG_DEBUG, "address: %s", address);
}
break;
case CB_CONF_ADMIN:
syslog(LOG_DEBUG, "user admin defined allowed");
break;
case CB_CONF_LIST:
break;
}
len -= opt_len;
}
cbcp_resp(us);
}
void cbcp_resp(cbcp_state *us)
{
u_char cb_type;
u_char buf[256];
u_char *bufp = buf;
int len = 0;
struct cbcp *cbcp;
cb_type = us->us_allowed & us->us_type;
syslog(LOG_DEBUG, "cbcp_resp cb_type=%d", cb_type);
cbcp = &lcp_wantoptions[ lns[us->us_unit].lcp_unit ].cbcp;
#if 0
if (!cb_type)
lcp_down( lns[us->us_unit].lcp_unit );
#endif
if (cb_type & ( 1 << CB_CONF_USER ) ) {
syslog(LOG_DEBUG, "cbcp_resp CONF_USER");
PUTCHAR(CB_CONF_USER, bufp);
len = 3 + 1 + strlen(cbcp->message) + 1;
PUTCHAR(len , bufp);
PUTCHAR(5, bufp); /* delay */
PUTCHAR(1, bufp);
#if 0
BCOPY(strlen(cbcp->message), bufp, strlen(cbcp->message) + 1);
#endif
cbcp_send(us, CBCP_RESP, buf, len);
return;
}
if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
PUTCHAR(CB_CONF_ADMIN, bufp);
len = 3;
PUTCHAR(len , bufp);
PUTCHAR(0, bufp);
cbcp_send(us, CBCP_RESP, buf, len);
return;
}
if (cb_type & ( 1 << CB_CONF_NO ) ) {
syslog(LOG_DEBUG, "cbcp_resp CONF_NO");
PUTCHAR(CB_CONF_NO, bufp);
len = 3;
PUTCHAR(len , bufp);
PUTCHAR(0, bufp);
cbcp_send(us, CBCP_RESP, buf, len);
#if 0
/*
* what should we do here ... check this! */
*/
ipcp_open( lns[us->us_unit].ipcp_unit );
#endif
return;
}
}
void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len)
{
u_char *outp;
int outlen;
outp = outpacket_buf;
outlen = 4 + len;
MAKEHEADER(outp, PPP_CBCP);
PUTCHAR(code, outp);
PUTCHAR(us->us_id, outp);
PUTSHORT(outlen, outp);
if (len)
BCOPY(buf, outp, len);
output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
}
void cbcp_recvack(cbcp_state *us, char *pckt, int len)
{
u_char type, delay, addr_type;
int opt_len;
char address[256];
if (len) {
GETCHAR(type, pckt);
GETCHAR(opt_len, pckt);
if (opt_len > 2)
GETCHAR(delay, pckt);
if (opt_len > 4) {
GETCHAR(addr_type, pckt);
memcpy(address, pckt, opt_len - 4);
address[opt_len - 4] = 0;
if (address[0])
syslog(LOG_DEBUG, "peer will call: %s", address);
}
}
cbcp_up(us);
}
/* ok peer will do callback */
void cbcp_up(cbcp_state *us)
{
int linkunit = us->us_unit;
lcp_close( lns[linkunit].lcp_unit ,"callback initiated sucessfully");
lns[linkunit].phase = PHASE_TERMINATE;
}

25
ipppd/cbcp.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef CBCP_H
#define CBCP_H
typedef struct cbcp_state {
int us_unit; /* Interface unit number */
u_char us_id; /* Current id */
int us_type;
int us_allowed;
} cbcp_state;
extern struct protent cbcp_protent;
extern cbcp_state cbcp[];
#define CBCP_MINLEN 4
#define CBCP_REQ 1
#define CBCP_RESP 2
#define CBCP_ACK 3
#define CB_CONF_NO 1
#define CB_CONF_USER 2
#define CB_CONF_ADMIN 3
#define CB_CONF_LIST 4
#endif

1004
ipppd/ccp.c Normal file

File diff suppressed because it is too large Load Diff

47
ipppd/ccp.h Normal file
View File

@ -0,0 +1,47 @@
/*
* ccp.h - Definitions for PPP Compression Control Protocol.
*
* Copyright (c) 1994 The Australian National University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, provided that the above copyright
* notice appears in all copies. This software is provided without any
* warranty, express or implied. The Australian National University
* makes no representations about the suitability of this software for
* any purpose.
*
* IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
* THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
*
* $Id: ccp.h,v 1.1 1997/03/07 16:01:11 hipp Exp $
*/
typedef struct ccp_options {
u_int bsd_compress: 1; /* do BSD Compress? */
u_int deflate: 1; /* do Deflate? */
u_int predictor_1: 1; /* do Predictor-1? */
u_int predictor_2: 1; /* do Predictor-2? */
u_short bsd_bits; /* # bits/code for BSD Compress */
u_short deflate_size; /* lg(window size) for Deflate */
short method; /* code for chosen compression method */
} ccp_options;
extern fsm ccp_fsm[];
extern ccp_options ccp_wantoptions[];
extern ccp_options ccp_gotoptions[];
extern ccp_options ccp_allowoptions[];
extern ccp_options ccp_hisoptions[];
extern struct protent ccp_protent;

843
ipppd/chap.c Normal file
View File

@ -0,0 +1,843 @@
/*
* chap.c - Crytographic Handshake Authentication Protocol.
*
* Copyright (c) 1991 Gregory M. Christy.
* 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 Gregory M. Christy. 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 lint
static char rcsid[] = "$Id: chap.c,v 1.1 1997/03/07 16:01:12 hipp Exp $";
#endif
/*
* TODO:
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <syslog.h>
#include "fsm.h"
#include "pppd.h"
#include "chap.h"
#ifdef USE_MSCHAP
#include "chap_ms.h"
#endif /* USE_MSCHAP */
#include "md5.h"
/*
* Protocol entry points.
*/
static void ChapInit __P((int));
static void ChapLowerUp __P((int));
static void ChapLowerDown __P((int));
static void ChapInput __P((int, u_char *, int));
static void ChapProtocolReject __P((int));
static int ChapPrintPkt __P((u_char *, int,
void (*) __P((void *, char *, ...)), void *));
struct protent chap_protent = {
PPP_CHAP,
ChapInit,
ChapInput,
ChapProtocolReject,
ChapLowerUp,
ChapLowerDown,
NULL,
NULL,
ChapPrintPkt,
NULL,
1,
"CHAP",
NULL,
NULL,
NULL
};
chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
static void ChapChallengeTimeout __P((caddr_t));
static void ChapResponseTimeout __P((caddr_t));
static void ChapReceiveChallenge __P((chap_state *, u_char *, int, int));
static void ChapReceiveResponse __P((chap_state *, u_char *, int, int));
static void ChapReceiveSuccess __P((chap_state *, u_char *, int, int));
static void ChapReceiveFailure __P((chap_state *, u_char *, int, int));
static void ChapSendStatus __P((chap_state *, int));
static void ChapSendChallenge __P((chap_state *));
static void ChapSendResponse __P((chap_state *));
static void ChapGenChallenge __P((chap_state *));
extern double drand48 __P((void));
extern void srand48 __P((long));
/*
* ChapInit - Initialize a CHAP unit.
*/
void
ChapInit(unit)
int unit;
{
chap_state *cstate = &chap[unit];
BZERO(cstate, sizeof(*cstate));
cstate->unit = unit;
cstate->clientstate = CHAPCS_INITIAL;
cstate->serverstate = CHAPSS_INITIAL;
cstate->timeouttime = CHAP_DEFTIMEOUT;
cstate->max_transmits = CHAP_DEFTRANSMITS;
/* random number generator is initialized in magic_init */
}
/*
* ChapAuthWithPeer - Authenticate us with our peer (start client).
*
*/
void
ChapAuthWithPeer(unit, our_name, digest)
int unit;
char *our_name;
int digest;
{
chap_state *cstate = &chap[unit];
cstate->resp_name = our_name;
cstate->resp_type = digest;
if (cstate->clientstate == CHAPCS_INITIAL ||
cstate->clientstate == CHAPCS_PENDING) {
/* lower layer isn't up - wait until later */
cstate->clientstate = CHAPCS_PENDING;
return;
}
/*
* We get here as a result of LCP coming up.
* So even if CHAP was open before, we will
* have to re-authenticate ourselves.
*/
cstate->clientstate = CHAPCS_LISTEN;
}
/*
* ChapAuthPeer - Authenticate our peer (start server).
*/
void
ChapAuthPeer(unit, our_name, digest)
int unit;
char *our_name;
int digest;
{
chap_state *cstate = &chap[unit];
cstate->chal_name = our_name;
cstate->chal_type = digest;
if (cstate->serverstate == CHAPSS_INITIAL ||
cstate->serverstate == CHAPSS_PENDING) {
/* lower layer isn't up - wait until later */
cstate->serverstate = CHAPSS_PENDING;
return;
}
ChapGenChallenge(cstate);
ChapSendChallenge(cstate); /* crank it up dude! */
cstate->serverstate = CHAPSS_INITIAL_CHAL;
}
/*
* ChapChallengeTimeout - Timeout expired on sending challenge.
*/
static void
ChapChallengeTimeout(arg)
caddr_t arg;
{
chap_state *cstate = (chap_state *) arg;
/* if we aren't sending challenges, don't worry. then again we */
/* probably shouldn't be here either */
if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
cstate->serverstate != CHAPSS_RECHALLENGE)
return;
if (cstate->chal_transmits >= cstate->max_transmits) {
/* give up on peer */
syslog(LOG_ERR, "Peer failed to respond to CHAP challenge");
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP);
return;
}
ChapSendChallenge(cstate); /* Re-send challenge */
}
/*
* ChapResponseTimeout - Timeout expired on sending response.
*/
static void
ChapResponseTimeout(arg)
caddr_t arg;
{
chap_state *cstate = (chap_state *) arg;
/* if we aren't sending a response, don't worry. */
if (cstate->clientstate != CHAPCS_RESPONSE)
return;
ChapSendResponse(cstate); /* re-send response */
}
/*
* ChapRechallenge - Time to challenge the peer again.
*/
static void
ChapRechallenge(arg)
caddr_t arg;
{
chap_state *cstate = (chap_state *) arg;
/* if we aren't sending a response, don't worry. */
if (cstate->serverstate != CHAPSS_OPEN)
return;
ChapGenChallenge(cstate);
ChapSendChallenge(cstate);
cstate->serverstate = CHAPSS_RECHALLENGE;
}
/*
* ChapLowerUp - The lower layer is up.
*
* Start up if we have pending requests.
*/
void
ChapLowerUp(unit)
int unit;
{
chap_state *cstate = &chap[unit];
if (cstate->clientstate == CHAPCS_INITIAL)
cstate->clientstate = CHAPCS_CLOSED;
else if (cstate->clientstate == CHAPCS_PENDING)
cstate->clientstate = CHAPCS_LISTEN;
if (cstate->serverstate == CHAPSS_INITIAL)
cstate->serverstate = CHAPSS_CLOSED;
else if (cstate->serverstate == CHAPSS_PENDING) {
ChapGenChallenge(cstate);
ChapSendChallenge(cstate);
cstate->serverstate = CHAPSS_INITIAL_CHAL;
}
}
/*
* ChapLowerDown - The lower layer is down.
*
* Cancel all timeouts.
*/
void
ChapLowerDown(unit)
int unit;
{
chap_state *cstate = &chap[unit];
/* Timeout(s) pending? Cancel if so. */
if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
cstate->serverstate == CHAPSS_RECHALLENGE)
UNTIMEOUT(ChapChallengeTimeout, (caddr_t) cstate);
else if (cstate->serverstate == CHAPSS_OPEN
&& cstate->chal_interval != 0)
UNTIMEOUT(ChapRechallenge, (caddr_t) cstate);
if (cstate->clientstate == CHAPCS_RESPONSE)
UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate);
cstate->clientstate = CHAPCS_INITIAL;
cstate->serverstate = CHAPSS_INITIAL;
}
/*
* ChapProtocolReject - Peer doesn't grok CHAP.
*/
void ChapProtocolReject(int linkunit)
{
int unit = lns[linkunit].chap_unit;
chap_state *cstate = &chap[unit];
if (cstate->serverstate != CHAPSS_INITIAL &&
cstate->serverstate != CHAPSS_CLOSED)
auth_peer_fail(cstate->unit, PPP_CHAP);
if (cstate->clientstate != CHAPCS_INITIAL &&
cstate->clientstate != CHAPCS_CLOSED)
auth_withpeer_fail(cstate->unit, PPP_CHAP);
ChapLowerDown(unit); /* shutdown chap */
}
/*
* ChapInput - Input CHAP packet.
*/
void ChapInput(int linkunit,u_char *inpacket,int packet_len)
{
int unit = lns[linkunit].chap_unit;
chap_state *cstate = &chap[unit];
u_char *inp;
u_char code, id;
int len;
/*
* Parse header (code, id and length).
* If packet too short, drop it.
*/
inp = inpacket;
if (packet_len < CHAP_HEADERLEN) {
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header."));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len < CHAP_HEADERLEN) {
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length."));
return;
}
if (len > packet_len) {
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet."));
return;
}
len -= CHAP_HEADERLEN;
/*
* Action depends on code (as in fact it usually does :-).
*/
switch (code) {
case CHAP_CHALLENGE:
ChapReceiveChallenge(cstate, inp, id, len);
break;
case CHAP_RESPONSE:
ChapReceiveResponse(cstate, inp, id, len);
break;
case CHAP_FAILURE:
ChapReceiveFailure(cstate, inp, id, len);
break;
case CHAP_SUCCESS:
ChapReceiveSuccess(cstate, inp, id, len);
break;
default: /* Need code reject? */
syslog(LOG_WARNING, "Unknown CHAP code (%d) received.", code);
break;
}
}
/*
* ChapReceiveChallenge - Receive Challenge and send Response.
*/
static void
ChapReceiveChallenge(cstate, inp, id, len)
chap_state *cstate;
u_char *inp;
int id;
int len;
{
int rchallenge_len;
u_char *rchallenge;
int secret_len;
char secret[MAXSECRETLEN];
char rhostname[256];
MD5_CTX mdContext;
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.", id));
if (cstate->clientstate == CHAPCS_CLOSED ||
cstate->clientstate == CHAPCS_PENDING) {
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d",
cstate->clientstate));
return;
}
if (len < 2) {
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet."));
return;
}
GETCHAR(rchallenge_len, inp);
len -= sizeof (u_char) + rchallenge_len; /* now name field length */
if (len < 0) {
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet."));
return;
}
rchallenge = inp;
INCPTR(rchallenge_len, inp);
if (len >= sizeof(rhostname))
len = sizeof(rhostname) - 1;
BCOPY(inp, rhostname, len);
rhostname[len] = '\000';
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field: '%s'",
rhostname));
#ifdef USE_MSCHAP
/* Microsoft doesn't send their name back in the PPP packet */
if (!rhostname[0] && cstate->resp_type == CHAP_MICROSOFT) {
extern char remote_name[];
strcpy(rhostname, remote_name);
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name", rhostname));
}
#endif /* USE_MSCHAP */
/* get secret for authenticating ourselves with the specified host */
if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
secret, &secret_len, 0)) {
secret_len = 0; /* assume null secret if can't find one */
syslog(LOG_WARNING, "No CHAP secret found for authenticating us to %s",
rhostname);
}
/* cancel response send timeout if necessary */
if (cstate->clientstate == CHAPCS_RESPONSE)
UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate);
cstate->resp_id = id;
cstate->resp_transmits = 0;
/* generate MD based on negotiated type */
switch (cstate->resp_type) {
case CHAP_DIGEST_MD5:
MD5Init(&mdContext);
MD5Update(&mdContext, &cstate->resp_id, 1);
MD5Update(&mdContext, secret, secret_len);
MD5Update(&mdContext, rchallenge, rchallenge_len);
MD5Final(&mdContext);
BCOPY(mdContext.digest, cstate->response, MD5_SIGNATURE_SIZE);
cstate->resp_length = MD5_SIGNATURE_SIZE;
break;
#ifdef USE_MSCHAP
case CHAP_MICROSOFT:
ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
break;
#endif /* USE_MSCHAP */
default:
CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->resp_type));
return;
}
ChapSendResponse(cstate);
}
/*
* ChapReceiveResponse - Receive and process response.
*/
static void
ChapReceiveResponse(cstate, inp, id, len)
chap_state *cstate;
u_char *inp;
int id;
int len;
{
u_char *remmd, remmd_len;
int secret_len, old_state;
int code;
char rhostname[256];
MD5_CTX mdContext;
char secret[MAXSECRETLEN];
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.", id));
if (cstate->serverstate == CHAPSS_CLOSED ||
cstate->serverstate == CHAPSS_PENDING) {
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d",
cstate->serverstate));
return;
}
if (id != cstate->chal_id)
return; /* doesn't match ID of last challenge */
/*
* If we have received a duplicate or bogus Response,
* we have to send the same answer (Success/Failure)
* as we did for the first Response we saw.
*/
if (cstate->serverstate == CHAPSS_OPEN) {
ChapSendStatus(cstate, CHAP_SUCCESS);
return;
}
if (cstate->serverstate == CHAPSS_BADAUTH) {
ChapSendStatus(cstate, CHAP_FAILURE);
return;
}
if (len < 2) {
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet."));
return;
}
GETCHAR(remmd_len, inp); /* get length of MD */
remmd = inp; /* get pointer to MD */
INCPTR(remmd_len, inp);
len -= sizeof (u_char) + remmd_len;
if (len < 0) {
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet."));
return;
}
UNTIMEOUT(ChapChallengeTimeout, (caddr_t) cstate);
if (len >= sizeof(rhostname))
len = sizeof(rhostname) - 1;
BCOPY(inp, rhostname, len);
rhostname[len] = '\000';
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s",
rhostname));
/*
* Get secret for authenticating them with us,
* do the hash ourselves, and compare the result.
*/
code = CHAP_FAILURE;
if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
secret, &secret_len, 1)) {
syslog(LOG_WARNING, "No CHAP secret found for authenticating %s",
rhostname);
} else {
/* generate MD based on negotiated type */
switch (cstate->chal_type) {
case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
if (remmd_len != MD5_SIGNATURE_SIZE)
break; /* it's not even the right length */
MD5Init(&mdContext);
MD5Update(&mdContext, &cstate->chal_id, 1);
MD5Update(&mdContext, secret, secret_len);
MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
MD5Final(&mdContext);
/* compare local and remote MDs and send the appropriate status */
if (memcmp (mdContext.digest, remmd, MD5_SIGNATURE_SIZE) == 0)
code = CHAP_SUCCESS; /* they are the same! */
break;
default:
CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->chal_type));
}
}
ChapSendStatus(cstate, code);
if (code == CHAP_SUCCESS) {
old_state = cstate->serverstate;
cstate->serverstate = CHAPSS_OPEN;
if (old_state == CHAPSS_INITIAL_CHAL) {
auth_peer_success(cstate->unit, PPP_CHAP);
}
if (cstate->chal_interval != 0)
TIMEOUT(ChapRechallenge, (caddr_t) cstate, cstate->chal_interval);
} else {
syslog(LOG_ERR, "CHAP peer authentication failed");
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP);
}
}
/*
* ChapReceiveSuccess - Receive Success
*/
static void
ChapReceiveSuccess(cstate, inp, id, len)
chap_state *cstate;
u_char *inp;
u_char id;
int len;
{
CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.", id));
if (cstate->clientstate == CHAPCS_OPEN)
/* presumably an answer to a duplicate response */
return;
if (cstate->clientstate != CHAPCS_RESPONSE) {
/* don't know what this is */
CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: in state %d\n",
cstate->clientstate));
return;
}
UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate);
/*
* Print message.
*/
if (len > 0)
PRINTMSG(inp, len);
cstate->clientstate = CHAPCS_OPEN;
auth_withpeer_success(cstate->unit, PPP_CHAP);
}
/*
* ChapReceiveFailure - Receive failure.
*/
static void
ChapReceiveFailure(cstate, inp, id, len)
chap_state *cstate;
u_char *inp;
u_char id;
int len;
{
CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.", id));
if (cstate->clientstate != CHAPCS_RESPONSE) {
/* don't know what this is */
CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n",
cstate->clientstate));
return;
}
UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate);
/*
* Print message.
*/
if (len > 0)
PRINTMSG(inp, len);
syslog(LOG_ERR, "CHAP authentication failed");
auth_withpeer_fail(cstate->unit, PPP_CHAP);
}
/*
* ChapSendChallenge - Send an Authenticate challenge.
*/
static void
ChapSendChallenge(cstate)
chap_state *cstate;
{
u_char *outp;
int chal_len, name_len;
int outlen;
chal_len = cstate->chal_len;
name_len = strlen(cstate->chal_name);
outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
PUTCHAR(CHAP_CHALLENGE, outp);
PUTCHAR(cstate->chal_id, outp);
PUTSHORT(outlen, outp);
PUTCHAR(chal_len, outp); /* put length of challenge */
BCOPY(cstate->challenge, outp, chal_len);
INCPTR(chal_len, outp);
BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.", cstate->chal_id));
TIMEOUT(ChapChallengeTimeout, (caddr_t) cstate, cstate->timeouttime);
++cstate->chal_transmits;
}
/*
* ChapSendStatus - Send a status response (ack or nak).
*/
static void
ChapSendStatus(cstate, code)
chap_state *cstate;
int code;
{
u_char *outp;
int outlen, msglen;
char msg[256];
if (code == CHAP_SUCCESS)
sprintf(msg, "Welcome to %s.", hostname);
else
sprintf(msg, "I don't like you. Go 'way.");
msglen = strlen(msg);
outlen = CHAP_HEADERLEN + msglen;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
PUTCHAR(code, outp);
PUTCHAR(cstate->chal_id, outp);
PUTSHORT(outlen, outp);
BCOPY(msg, outp, msglen);
output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.", code,
cstate->chal_id));
}
/*
* ChapGenChallenge is used to generate a pseudo-random challenge string of
* a pseudo-random length between min_len and max_len. The challenge
* string and its length are stored in *cstate, and various other fields of
* *cstate are initialized.
*/
static void
ChapGenChallenge(cstate)
chap_state *cstate;
{
int chal_len;
u_char *ptr = cstate->challenge;
unsigned int i;
/* pick a random challenge length between MIN_CHALLENGE_LENGTH and
MAX_CHALLENGE_LENGTH */
chal_len = (unsigned) ((drand48() *
(MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
MIN_CHALLENGE_LENGTH);
cstate->chal_len = chal_len;
cstate->chal_id = ++cstate->id;
cstate->chal_transmits = 0;
/* generate a random string */
for (i = 0; i < chal_len; i++ )
*ptr++ = (char) (drand48() * 0xff);
}
/*
* ChapSendResponse - send a response packet with values as specified
* in *cstate.
*/
/* ARGSUSED */
static void
ChapSendResponse(cstate)
chap_state *cstate;
{
u_char *outp;
int outlen, md_len, name_len;
md_len = cstate->resp_length;
name_len = strlen(cstate->resp_name);
outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_CHAP);
PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
PUTSHORT(outlen, outp); /* packet length */
PUTCHAR(md_len, outp); /* length of MD */
BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
INCPTR(md_len, outp);
BCOPY(cstate->resp_name, outp, name_len); /* append our name */
/* send the packet */
output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
cstate->clientstate = CHAPCS_RESPONSE;
TIMEOUT(ChapResponseTimeout, (caddr_t) cstate, cstate->timeouttime);
++cstate->resp_transmits;
}
/*
* ChapPrintPkt - print the contents of a CHAP packet.
*/
char *ChapCodenames[] = {
"Challenge", "Response", "Success", "Failure"
};
int
ChapPrintPkt(p, plen, printer, arg)
u_char *p;
int plen;
void (*printer) __P((void *, char *, ...));
void *arg;
{
int code, id, len;
int clen, nlen;
u_char x;
if (plen < CHAP_HEADERLEN)
return 0;
GETCHAR(code, p);
GETCHAR(id, p);
GETSHORT(len, p);
if (len < CHAP_HEADERLEN || len > plen)
return 0;
if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *))
printer(arg, " %s", ChapCodenames[code-1]);
else
printer(arg, " code=0x%x", code);
printer(arg, " id=0x%x", id);
len -= CHAP_HEADERLEN;
switch (code) {
case CHAP_CHALLENGE:
case CHAP_RESPONSE:
if (len < 1)
break;
clen = p[0];
if (len < clen + 1)
break;
++p;
nlen = len - clen - 1;
printer(arg, " <");
for (; clen > 0; --clen) {
GETCHAR(x, p);
printer(arg, "%.2x", x);
}
printer(arg, ">, name = ");
print_string((char *)p, nlen, printer, arg);
break;
case CHAP_FAILURE:
case CHAP_SUCCESS:
printer(arg, " ");
print_string((char *)p, len, printer, arg);
break;
default:
for (clen = len; clen > 0; --clen) {
GETCHAR(x, p);
printer(arg, " %.2x", x);
}
}
return len + CHAP_HEADERLEN;
}

107
ipppd/chap.h Normal file
View File

@ -0,0 +1,107 @@
/*
* chap.h - Cryptographic Handshake Authentication Protocol definitions.
*
* Copyright (c) 1991 Gregory M. Christy
* 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 the author.
*
* 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.
*
* $Id: chap.h,v 1.1 1997/03/07 16:01:13 hipp Exp $
*/
#ifndef __CHAP_INCLUDE__
/* Code + ID + length */
#define CHAP_HEADERLEN 4
/*
* CHAP codes.
*/
#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */
#define CHAP_MICROSOFT 0x80 /* Use vendor specific:Microsoft */
#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */
#define CHAP_CHALLENGE 1
#define CHAP_RESPONSE 2
#define CHAP_SUCCESS 3
#define CHAP_FAILURE 4
/*
* Challenge lengths (for challenges we send) and other limits.
*/
#define MIN_CHALLENGE_LENGTH 32
#define MAX_CHALLENGE_LENGTH 64
#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 and MSCHAP */
/*
* Each interface is described by a chap structure.
*/
typedef struct chap_state {
int unit; /* Interface unit number */
int clientstate; /* Client state */
int serverstate; /* Server state */
u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */
u_char chal_len; /* challenge length */
u_char chal_id; /* ID of last challenge */
u_char chal_type; /* hash algorithm for challenges */
u_char id; /* Current id */
char *chal_name; /* Our name to use with challenge */
int chal_interval; /* Time until we challenge peer again */
int timeouttime; /* Timeout time in seconds */
int max_transmits; /* Maximum # of challenge transmissions */
int chal_transmits; /* Number of transmissions of challenge */
int resp_transmits; /* Number of transmissions of response */
u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */
u_char resp_length; /* length of response */
u_char resp_id; /* ID for response messages */
u_char resp_type; /* hash algorithm for responses */
char *resp_name; /* Our name to send with response */
} chap_state;
/*
* Client (peer) states.
*/
#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */
#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */
#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */
#define CHAPCS_LISTEN 3 /* Listening for a challenge */
#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */
#define CHAPCS_OPEN 5 /* We've received Success */
/*
* Server (authenticator) states.
*/
#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */
#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */
#define CHAPSS_PENDING 2 /* Auth peer when lower up */
#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */
#define CHAPSS_OPEN 4 /* We've sent a Success msg */
#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */
#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */
/*
* Timeouts.
*/
#define CHAP_DEFTIMEOUT 3 /* Timeout time in seconds */
#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */
extern chap_state chap[];
extern struct protent chap_protent;
void ChapAuthWithPeer __P((int, char *, int));
void ChapAuthPeer __P((int, char *, int));
#define __CHAP_INCLUDE__
#endif /* __CHAP_INCLUDE__ */

180
ipppd/chap_ms.c Normal file
View File

@ -0,0 +1,180 @@
/*
* chap_ms.c - Microsoft MS-CHAP compatible implementation.
*
* 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.
*/
#ifdef USE_MSCHAP
#ifndef lint
static char rcsid[] = "$Id: chap_ms.c,v 1.1 1997/03/07 16:01:14 hipp Exp $";
#endif
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <syslog.h>
#include "pppd.h"
#include "chap.h"
#include "chap_ms.h"
#include "md4.h"
#include <des.h>
typedef struct {
u_char LANManResp[24];
u_char NTResp[24];
u_char UseNT; /* If 1, ignore the LANMan response field */
} MS_ChapResponse;
#define MS_CHAP_RESPONSE_LEN 49 /* Don't rely on sizeof(MS_ChapResponse) in case of struct padding */
static void DesEncrypt __P((u_char *, u_char *, u_char *));
static void MakeKey __P((u_char *, u_char *));
static void
ChallengeResponse(challenge, pwHash, response)
u_char *challenge; /* IN 8 octets */
u_char *pwHash; /* IN 16 octets */
u_char *response; /* OUT 24 octets */
{
char ZPasswordHash[21];
BZERO(ZPasswordHash, sizeof(ZPasswordHash));
BCOPY(pwHash, ZPasswordHash, 16);
#if 0
log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash");
#endif
DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
#if 0
log_packet(response, 24, "ChallengeResponse - response");
#endif
}
static void
DesEncrypt(clear, key, cipher)
u_char *clear; /* IN 8 octets */
u_char *key; /* IN 7 octets */
u_char *cipher; /* OUT 8 octets */
{
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 : %02X%02X%02X%02X%02X%02X%02X%02X",
clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
#endif
des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
#if 0
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X",
cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
#endif
}
static u_char Get7Bits(input, startBit)
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;
}
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);
des_set_odd_parity((des_cblock *)des_key);
#if 0
CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X",
key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X",
des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
#endif
}
#endif /* USE_MSCHAP */
void
ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len)
chap_state *cstate;
char *rchallenge;
int rchallenge_len;
char *secret;
int secret_len;
{
#ifdef USE_MSCHAP
int i;
MDstruct md4Context;
MS_ChapResponse response;
u_char unicodePassword[MAX_NT_PASSWORD * 2];
#if 0
CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
#endif
BZERO(&response, sizeof(response));
/* Initialize the Unicode version of the secret (== password). */
/* This implicitly supports 8-bit ISO8859/1 characters. */
BZERO(unicodePassword, sizeof(unicodePassword));
for (i = 0; i < secret_len; i++)
unicodePassword[i * 2] = (u_char)secret[i];
MDbegin(&md4Context);
MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */
MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */
ChallengeResponse(rchallenge, (char *)md4Context.buffer, response.NTResp);
response.UseNT = 1;
BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
cstate->resp_length = MS_CHAP_RESPONSE_LEN;
#endif /* USE_MSCHAP */
}

32
ipppd/chap_ms.h Normal file
View File

@ -0,0 +1,32 @@
/*
* chap.h - Cryptographic Handshake Authentication Protocol definitions.
*
* 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.
*
* $Id: chap_ms.h,v 1.1 1997/03/07 16:01:15 hipp Exp $
*/
#ifndef __CHAPMS_INCLUDE__
#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */
void ChapMS __P((chap_state *, char *, int, char *, int));
#define __CHAPMS_INCLUDE__
#endif /* __CHAPMS_INCLUDE__ */

747
ipppd/fsm.c Normal file
View File

@ -0,0 +1,747 @@
/*
* fsm.c - {Link, IP} Control Protocol Finite State Machine.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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 lint
static char rcsid[] = "$Id: fsm.c,v 1.1 1997/03/07 16:01:15 hipp Exp $";
#endif
/*
* TODO:
* Randomize fsm id on link/init.
* Deal with variable outgoing MTU.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <syslog.h>
#include "fsm.h"
#include "pppd.h"
#include "lcp.h"
extern char *proto_name();
static void fsm_timeout __P((caddr_t));
static void fsm_rconfreq __P((fsm *, int, u_char *, int));
static void fsm_rconfack __P((fsm *, int, u_char *, int));
static void fsm_rconfnakrej __P((fsm *, int, int, u_char *, int));
static void fsm_rtermreq __P((fsm *, int, u_char *, int));
static void fsm_rtermack __P((fsm *));
static void fsm_rcoderej __P((fsm *, u_char *, int));
static void fsm_sconfreq __P((fsm *, int));
#define PROTO_NAME(f) ((f)->callbacks->proto_name)
/*
* fsm_init - Initialize fsm.
*
* Initialize fsm state.
*/
void fsm_init(fsm *f)
{
f->state = INITIAL;
f->flags = 0;
f->id = 0; /* XXX Start with random id? */
f->timeouttime = DEFTIMEOUT;
f->maxconfreqtransmits = DEFMAXCONFREQS;
f->maxtermtransmits = DEFMAXTERMREQS;
f->maxnakloops = DEFMAXNAKLOOPS;
f->term_reason_len = 0;
}
/*
* fsm_lowerup - The lower layer is up.
*/
void fsm_lowerup(fsm *f)
{
switch( f->state ){
case INITIAL:
f->state = CLOSED;
break;
case STARTING:
if( f->flags & OPT_SILENT )
f->state = STOPPED;
else {
/* Send an initial configure-request */
fsm_sconfreq(f, 0);
f->state = REQSENT;
}
break;
default:
FSMDEBUG((LOG_INFO, "%s: Up event in state %d!",
PROTO_NAME(f), f->state));
}
}
/*
* fsm_lowerdown - The lower layer is down.
*
* Cancel all timeouts and inform upper layers.
*/
void fsm_lowerdown(fsm *f)
{
switch( f->state ){
case CLOSED:
f->state = INITIAL;
break;
case STOPPED:
f->state = STARTING;
if( f->callbacks->starting )
(*f->callbacks->starting)(f);
break;
case CLOSING:
f->state = INITIAL;
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
break;
case STOPPING:
case REQSENT:
case ACKRCVD:
case ACKSENT:
f->state = STARTING;
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
break;
case OPENED:
if( f->callbacks->down )
(*f->callbacks->down)(f);
f->state = STARTING;
break;
default:
FSMDEBUG((LOG_INFO, "%s: Down event in state %d!",
PROTO_NAME(f), f->state));
}
}
/*
* fsm_open - Link is allowed to come up.
*/
void fsm_open(fsm *f)
{
switch( f->state ){
case INITIAL:
f->state = STARTING;
if( f->callbacks->starting )
(*f->callbacks->starting)(f);
break;
case CLOSED:
if( f->flags & OPT_SILENT )
f->state = STOPPED;
else {
/* Send an initial configure-request */
fsm_sconfreq(f, 0);
f->state = REQSENT;
}
break;
case CLOSING:
f->state = STOPPING;
/* fall through */
case STOPPED:
case OPENED:
if( f->flags & OPT_RESTART ){
fsm_lowerdown(f);
fsm_lowerup(f);
}
break;
}
}
/*
* fsm_close - Start closing connection.
*
* Cancel timeouts and either initiate close or possibly go directly to
* the CLOSED state.
*/
void fsm_close(fsm *f,char *reason)
{
f->term_reason = reason;
f->term_reason_len = (reason == NULL? 0: strlen(reason));
switch( f->state ){
case STARTING:
f->state = INITIAL;
break;
case STOPPED:
f->state = CLOSED;
break;
case STOPPING:
f->state = CLOSING;
break;
case REQSENT:
case ACKRCVD:
case ACKSENT:
case OPENED:
if( f->state != OPENED )
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
else if( f->callbacks->down )
(*f->callbacks->down)(f); /* Inform upper layers we're down */
/* Init restart counter, send Terminate-Request */
f->retransmits = f->maxtermtransmits;
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
(u_char *) f->term_reason, f->term_reason_len);
TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
--f->retransmits;
f->state = CLOSING;
break;
}
}
/*
* fsm_timeout - Timeout expired.
*/
static void fsm_timeout(caddr_t arg)
{
fsm *f = (fsm *) arg;
switch (f->state) {
case CLOSING:
case STOPPING:
if( f->retransmits <= 0 ){
/*
* We've waited for an ack long enough. Peer probably heard us.
*/
f->state = (f->state == CLOSING)? CLOSED: STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
} else {
/* Send Terminate-Request */
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
(u_char *) f->term_reason, f->term_reason_len);
TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
--f->retransmits;
}
break;
case REQSENT:
case ACKRCVD:
case ACKSENT:
if (f->retransmits <= 0) {
syslog(LOG_WARNING, "%s: timeout sending Config-Requests",
PROTO_NAME(f));
f->state = STOPPED;
if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
(*f->callbacks->finished)(f);
} else {
/* Retransmit the configure-request */
if (f->callbacks->retransmit)
(*f->callbacks->retransmit)(f);
fsm_sconfreq(f, 1); /* Re-send Configure-Request */
if( f->state == ACKRCVD )
f->state = REQSENT;
}
break;
default:
FSMDEBUG((LOG_INFO, "%s: Timeout event in state %d!",
PROTO_NAME(f), f->state));
}
}
/*
* fsm_input - Input packet.
*/
void fsm_input(fsm *f,u_char *inpacket,int l)
{
u_char *inp;
u_char code, id;
int len;
/*
* Parse header (code, id and length).
* If packet too short, drop it.
*/
inp = inpacket;
if (l < HEADERLEN) {
FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.",
f->protocol));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len < HEADERLEN) {
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.",
f->protocol));
return;
}
if (len > l) {
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.",
f->protocol));
return;
}
len -= HEADERLEN; /* subtract header length */
if( f->state == INITIAL || f->state == STARTING ){
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d.",
f->protocol, f->state));
return;
}
/*
* Action depends on code.
*/
switch (code) {
case CONFREQ:
fsm_rconfreq(f, id, inp, len);
break;
case CONFACK:
fsm_rconfack(f, id, inp, len);
break;
case CONFNAK:
case CONFREJ:
fsm_rconfnakrej(f, code, id, inp, len);
break;
case TERMREQ:
fsm_rtermreq(f, id, inp, len);
break;
case TERMACK:
fsm_rtermack(f);
break;
case CODEREJ:
fsm_rcoderej(f, inp, len);
break;
default:
if( !f->callbacks->extcode
|| !(*f->callbacks->extcode)(f, code, id, inp, len) )
fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
break;
}
}
/*
* fsm_rconfreq - Receive Configure-Request.
*/
static void fsm_rconfreq(fsm *f,int id,u_char *inp,int len)
{
int code, reject_if_disagree;
FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d.", PROTO_NAME(f), id));
switch( f->state ){
case CLOSED:
/* Go away, we're closed */
fsm_sdata(f, TERMACK, id, NULL, 0);
return;
case CLOSING:
case STOPPING:
return;
case OPENED:
/* Go down and restart negotiation */
if( f->callbacks->down )
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
break;
case STOPPED:
/* Negotiation started by our peer */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
}
/*
* Pass the requested configuration options
* to protocol-specific code for checking.
*/
if (f->callbacks->reqci){ /* Check CI */
reject_if_disagree = (f->nakloops >= f->maxnakloops);
code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
} else if (len)
code = CONFREJ; /* Reject all CI */
else
code = CONFACK;
/* send the Ack, Nak or Rej to the peer */
fsm_sdata(f, code, id, inp, len);
if (code == CONFACK) {
if (f->state == ACKRCVD) {
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
f->state = OPENED;
if (f->callbacks->up)
(*f->callbacks->up)(f); /* Inform upper layers */
} else
f->state = ACKSENT;
f->nakloops = 0;
} else {
/* we sent CONFACK or CONFREJ */
if (f->state != ACKRCVD)
f->state = REQSENT;
if( code == CONFNAK )
++f->nakloops;
}
}
/*
* fsm_rconfack - Receive Configure-Ack.
*/
static void fsm_rconfack(fsm *f,int id,u_char *inp,int len)
{
FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d.",
PROTO_NAME(f), id));
if (id != f->reqid || f->seen_ack) /* Expected id? */
return; /* Nope, toss... */
if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
(len == 0)) ){
/* Ack is bad - ignore it */
FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)",
PROTO_NAME(f), len));
return;
}
f->seen_ack = 1;
switch (f->state) {
case CLOSED:
case STOPPED:
fsm_sdata(f, TERMACK, id, NULL, 0);
break;
case REQSENT:
f->state = ACKRCVD;
f->retransmits = f->maxconfreqtransmits;
break;
case ACKRCVD:
/* Huh? an extra valid Ack? oh well... */
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
fsm_sconfreq(f, 0);
f->state = REQSENT;
break;
case ACKSENT:
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
f->state = OPENED;
f->retransmits = f->maxconfreqtransmits;
if (f->callbacks->up)
(*f->callbacks->up)(f); /* Inform upper layers */
break;
case OPENED:
/* Go down and restart negotiation */
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
}
}
/*
* fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
*/
static void fsm_rconfnakrej(fsm *f,int code,int id,u_char *inp,int len)
{
int (*proc)();
int ret;
FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d.",
PROTO_NAME(f), id));
if (id != f->reqid || f->seen_ack) /* Expected id? */
return; /* Nope, toss... */
proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
if (!proc || !(ret = proc(f, inp, len))) {
/* Nak/reject is bad - ignore it */
FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)",
PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
return;
}
f->seen_ack = 1;
switch (f->state) {
case CLOSED:
case STOPPED:
fsm_sdata(f, TERMACK, id, NULL, 0);
break;
case REQSENT:
case ACKSENT:
/* They didn't agree to what we wanted - try another request */
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
if (ret < 0)
f->state = STOPPED; /* kludge for stopping CCP */
else
fsm_sconfreq(f, 0); /* Send Configure-Request */
break;
case ACKRCVD:
/* Got a Nak/reject when we had already had an Ack?? oh well... */
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
fsm_sconfreq(f, 0);
f->state = REQSENT;
break;
case OPENED:
/* Go down and restart negotiation */
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
}
}
/*
* fsm_rtermreq - Receive Terminate-Req.
*/
static void fsm_rtermreq(fsm *f,int id,u_char *p,int len)
{
char str[80];
FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d.",
PROTO_NAME(f), id));
switch (f->state) {
case ACKRCVD:
case ACKSENT:
f->state = REQSENT; /* Start over but keep trying */
break;
case OPENED:
if (len > 0) {
fmtmsg(str, sizeof(str), "%0.*v", len, p);
syslog(LOG_INFO, "%s terminated by peer (%s)", PROTO_NAME(f), str);
} else
syslog(LOG_INFO, "%s terminated by peer", PROTO_NAME(f));
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
f->retransmits = 0;
f->state = STOPPING;
TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
break;
}
fsm_sdata(f, TERMACK, id, NULL, 0);
}
/*
* fsm_rtermack - Receive Terminate-Ack.
*/
static void fsm_rtermack(fsm *f)
{
FSMDEBUG((LOG_INFO, "fsm_rtermack(%s).", PROTO_NAME(f)));
switch (f->state) {
case CLOSING:
UNTIMEOUT(fsm_timeout, (caddr_t) f);
f->state = CLOSED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case STOPPING:
UNTIMEOUT(fsm_timeout, (caddr_t) f);
f->state = STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case ACKRCVD:
f->state = REQSENT;
break;
case OPENED:
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0);
break;
}
}
/*
* fsm_rcoderej - Receive an Code-Reject.
*/
static void fsm_rcoderej(fsm *f,u_char *inp,int len)
{
u_char code, id;
FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s).", PROTO_NAME(f)));
if (len < HEADERLEN) {
FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!"));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
syslog(LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d",
PROTO_NAME(f), code, id);
if( f->state == ACKRCVD )
f->state = REQSENT;
}
/*
* fsm_protreject - Peer doesn't speak this protocol.
*
* Treat this as a catastrophic error (RXJ-).
*/
void fsm_protreject(fsm *f)
{
switch( f->state ){
case CLOSING:
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
/* fall through */
case CLOSED:
f->state = CLOSED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case STOPPING:
case REQSENT:
case ACKRCVD:
case ACKSENT:
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
/* fall through */
case STOPPED:
f->state = STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case OPENED:
if( f->callbacks->down )
(*f->callbacks->down)(f);
/* Init restart counter, send Terminate-Request */
f->retransmits = f->maxtermtransmits;
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
(u_char *) f->term_reason, f->term_reason_len);
TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
--f->retransmits;
f->state = STOPPING;
break;
default:
FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d!",
PROTO_NAME(f), f->state));
}
}
/*
* fsm_sconfreq - Send a Configure-Request.
*/
static void fsm_sconfreq(fsm *f,int retransmit)
{
u_char *outp;
int cilen;
if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
/* Not currently negotiating - reset options */
if( f->callbacks->resetci )
(*f->callbacks->resetci)(f);
f->nakloops = 0;
}
if( !retransmit ){
/* New request - reset retransmission counter, use new ID */
f->retransmits = f->maxconfreqtransmits;
f->reqid = ++f->id;
}
f->seen_ack = 0;
/*
* Make up the request packet
*/
outp = outpacket_buf + PPP_HDRLEN + HEADERLEN;
if( f->callbacks->cilen && f->callbacks->addci ){
cilen = (*f->callbacks->cilen)(f);
if( cilen > lns[f->unit].peer_mru - HEADERLEN )
cilen = lns[f->unit].peer_mru - HEADERLEN;
if (f->callbacks->addci)
(*f->callbacks->addci)(f, outp, &cilen);
} else
cilen = 0;
/* send the request to our peer */
fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
/* start the retransmit timer */
--f->retransmits;
TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d",
PROTO_NAME(f), f->reqid));
}
/*
* fsm_sdata - Send some data.
*
* Used for all packets sent to our peer by this module.
*/
void fsm_sdata(fsm *f,int code,int id,u_char *data,int datalen)
{
u_char *outp;
int outlen;
/* Adjust length to be smaller than MTU */
outp = outpacket_buf;
if (datalen > lns[f->unit].peer_mru - HEADERLEN)
datalen = lns[f->unit].peer_mru - HEADERLEN;
if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)
BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
outlen = datalen + HEADERLEN;
MAKEHEADER(outp, f->protocol);
PUTCHAR(code, outp);
PUTCHAR(id, outp);
PUTSHORT(outlen, outp);
output(f->unit, outpacket_buf, outlen + PPP_HDRLEN);
FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d, id %d.",
PROTO_NAME(f), code, id));
}

127
ipppd/fsm.h Normal file
View File

@ -0,0 +1,127 @@
/*
* fsm.h - {Link, IP} Control Protocol Finite State Machine definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id: fsm.h,v 1.1 1997/03/07 16:01:16 hipp Exp $
*/
/*
* Packet header = Code, id, length.
*/
#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short))
/*
* CP (LCP, IPCP, etc.) codes.
*/
#define CONFREQ 1 /* Configuration Request */
#define CONFACK 2 /* Configuration Ack */
#define CONFNAK 3 /* Configuration Nak */
#define CONFREJ 4 /* Configuration Reject */
#define TERMREQ 5 /* Termination Request */
#define TERMACK 6 /* Termination Ack */
#define CODEREJ 7 /* Code Reject */
/*
* Each FSM is described by a fsm_callbacks and a fsm structure.
*/
typedef struct fsm_callbacks {
void (*resetci)(); /* Reset our Configuration Information */
int (*cilen)(); /* Length of our Configuration Information */
void (*addci)(); /* Add our Configuration Information */
int (*ackci)(); /* ACK our Configuration Information */
int (*nakci)(); /* NAK our Configuration Information */
int (*rejci)(); /* Reject our Configuration Information */
int (*reqci)(); /* Request peer's Configuration Information */
void (*up)(); /* Called when fsm reaches OPENED state */
void (*down)(); /* Called when fsm leaves OPENED state */
void (*starting)(); /* Called when we want the lower layer */
void (*finished)(); /* Called when we don't want the lower layer */
void (*protreject)(); /* Called when Protocol-Reject received */
void (*retransmit)(); /* Retransmission is necessary */
int (*extcode)(); /* Called when unknown code received */
char *proto_name; /* String name for protocol (for messages) */
} fsm_callbacks;
typedef struct fsm {
int unit; /* Interface unit number */
int inuse; /* this 'unit' in use? */
int protocol; /* Data Link Layer Protocol field value */
int state; /* State */
int flags; /* Contains option bits */
u_char id; /* Current id */
u_char reqid; /* Current request id */
u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */
int timeouttime; /* Timeout time in milliseconds */
int maxconfreqtransmits; /* Maximum Configure-Request transmissions */
int retransmits; /* Number of retransmissions left */
int maxtermtransmits; /* Maximum Terminate-Request transmissions */
int nakloops; /* Number of nak loops since last ack */
int maxnakloops; /* Maximum number of nak loops tolerated */
fsm_callbacks *callbacks; /* Callback routines */
char *term_reason; /* Reason for closing protocol */
int term_reason_len; /* Length of term_reason */
} fsm;
/*
* Link states.
*/
#define INITIAL 0 /* Down, hasn't been opened */
#define STARTING 1 /* Down, been opened */
#define CLOSED 2 /* Up, hasn't been opened */
#define STOPPED 3 /* Open, waiting for down event */
#define CLOSING 4 /* Terminating the connection, not open */
#define STOPPING 5 /* Terminating, but open */
#define REQSENT 6 /* We've sent a Config Request */
#define ACKRCVD 7 /* We've received a Config Ack */
#define ACKSENT 8 /* We've sent a Config Ack */
#define OPENED 9 /* Connection available */
/*
* Flags - indicate options controlling FSM operation
*/
#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
#define OPT_SILENT 4 /* Wait for peer to speak first */
/*
* Timeouts.
*/
#define DEFTIMEOUT 3 /* Timeout time in seconds */
#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
/*
* Prototypes
*/
void fsm_init __P((fsm *));
void fsm_lowerup __P((fsm *));
void fsm_lowerdown __P((fsm *));
void fsm_open __P((fsm *));
void fsm_close __P((fsm *,char *));
void fsm_input __P((fsm *, u_char *, int));
void fsm_protreject __P((fsm *));
void fsm_sdata __P((fsm *, int, int, u_char *, int));

1307
ipppd/ipcp.c Normal file

File diff suppressed because it is too large Load Diff

69
ipppd/ipcp.h Normal file
View File

@ -0,0 +1,69 @@
/*
* ipcp.h - IP Control Protocol definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id: ipcp.h,v 1.1 1997/03/07 16:01:19 hipp Exp $
*/
/*
* Options.
*/
#define CI_ADDRS 1 /* IP Addresses */
#define CI_COMPRESSTYPE 2 /* Compression Type */
#define CI_ADDR 3
#define CI_MS_DNS1 129 /* Primary DNS value */
#define CI_MS_WINS1 130 /* Primary WINS value */
#define CI_MS_DNS2 131 /* Secondary DNS value */
#define CI_MS_WINS2 132 /* Secondary WINS value */
#define MAX_STATES 16 /* from slcompress.h */
#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */
#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */
#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */
/* maxslot and slot number compression) */
#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/
#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */
/* compression option*/
typedef struct ipcp_options {
int neg_addr : 1; /* Negotiate IP Address? */
int old_addrs : 1; /* Use old (IP-Addresses) option? */
int req_addr : 1; /* Ask peer to send IP address? */
int default_route : 1; /* Assign default route through interface? */
int proxy_arp : 1; /* Make proxy ARP entry for peer? */
int neg_vj : 1; /* Van Jacobson Compression? */
int old_vj : 1; /* use old (short) form of VJ option? */
int accept_local : 1; /* accept peer's value for ouraddr */
int accept_remote : 1; /* accept peer's value for hisaddr */
u_short vj_protocol; /* protocol value to use in VJ option */
u_char maxslotindex, cflag; /* values for RFC1332 VJ compression neg. */
u_int32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */
u_int32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */
u_int32_t winsaddr[2]; /* Primary and secondary MS WINS entries */
} ipcp_options;
extern fsm ipcp_fsm[];
extern ipcp_options ipcp_wantoptions[];
extern ipcp_options ipcp_gotoptions[];
extern ipcp_options ipcp_allowoptions[];
extern ipcp_options ipcp_hisoptions[];
extern struct protent ipcp_protent;

931
ipppd/ipppd.8 Normal file
View File

@ -0,0 +1,931 @@
.\" manual page [] for pppd 2.0
.\" $Id: ipppd.8,v 1.1 1997/03/07 16:01:19 hipp Exp $
.\" SH section heading
.\" SS subsection heading
.\" LP paragraph
.\" IP indented paragraph
.\" TP hanging label
.TH PPPD 8
.SH NAME
pppd \- Point to Point Protocol daemon
.SH SYNOPSIS
.B pppd
[
.I tty_name
] [
.I speed
] [
.I options
]
.SH DESCRIPTION
.LP
The Point-to-Point Protocol (PPP) provides a method for transmitting
datagrams over serial point-to-point links. PPP
is composed of three parts: a method for encapsulating datagrams over
serial links, an extensible Link Control Protocol (LCP), and
a family of Network Control Protocols (NCP) for establishing
and configuring different network-layer protocols.
.LP
The encapsulation scheme is provided by driver code in the kernel.
.B pppd
provides the basic LCP, authentication support, and an
NCP for establishing and configuring the Internet Protocol (IP)
(called the IP Control Protocol, IPCP).
.SH FREQUENTLY USED OPTIONS
.TP
.I <tty_name>
Communicate over the named device. The string "/dev/"
is prepended if necessary. If no device name is given,
or if the name of the controlling terminal is given,
.I pppd
will use the controlling terminal, and will not fork to put itself in
the background.
.TP
.I <speed>
Set the baud rate to <speed> (a decimal number). On systems such as
4.4BSD and NetBSD, any speed can be specified. Other systems
(e.g. SunOS) allow only a limited set of speeds.
.TP
.B asyncmap \fI<map>
Set the async character map to <map>.
This map describes which control characters cannot be successfully
received over the serial line.
.I pppd
will ask the peer to send these characters as a 2-byte escape sequence.
The argument is a 32 bit hex number
with each bit representing a character to escape.
Bit 0 (00000001) represents the character 0x00;
bit 31 (80000000) represents the character 0x1f or ^_.
If multiple \fBasyncmap\fR options are
given, the values are ORed together.
If no \fBasyncmap\fR option is given, no async character map will be
negotiated for the receive direction; the peer should then escape
\fIall\fR control characters.
.TP
.B auth
Require the peer to authenticate itself before allowing network
packets to be sent or received.
.TP
.B connect \fI<p>
Use the executable or shell command specified by \fI<p>\fR to set up the
serial line. This script would typically use the chat(8) program to
dial the modem and start the remote ppp session.
.TP
.B crtscts
Use hardware flow control (i.e. RTS/CTS) to control the flow of data
on the serial port. If neither the \fBcrtscts\fR nor the
\fB\-crtscts\fR option is given, the hardware flow control setting for
the serial port is left unchanged.
.TP
.B defaultroute
Add a default route to the system routing tables, using the peer as
the gateway, when IPCP negotiation is successfully completed.
This entry is removed when the PPP connection is broken.
.TP
.B disconnect \fI<p>
Run the executable or shell command specified by \fI<p>\fR after
\fIpppd\fR has terminated the link. This script could, for example,
issue commands to the modem to cause it to hang up if hardware modem
control signals were not available.
.TP
.B escape \fIxx,yy,...
Specifies that certain characters should be escaped on transmission
(regardless of whether the peer requests them to be escaped with its
async control character map). The characters to be escaped are
specified as a list of hex numbers separated by commas. Note that
almost any character can be specified for the \fBescape\fR option,
unlike the \fBasyncmap\fR option which only allows control characters
to be specified. The characters which may not be escaped are those
with hex values 0x20 - 0x3f or 0x5e.
.TP
.B file \fI<f>
Read options from file <f> (the format is described below).
.TP
.B lock
Specifies that \fIpppd\fR should create a UUCP-style lock file for the
serial device to ensure exclusive access to the device.
.TP
.B mru \fI<n>
Set the MRU [Maximum Receive Unit] value to <n> for negotiation.
.I pppd
will ask the peer to send packets of no more than <n> bytes. The
minimum MRU value is 128. The default MRU value is 1500. A value of
296 is recommended for slow links (40 bytes for TCP/IP header + 256
bytes of data).
.TP
.B mtu \fI<n>
Set the MTU [Maximum Transmit Unit] value to \fI<n>\fR. Unless the
peer requests a smaller value via MRU negotiation, \fIpppd\fR will
request that the kernel networking code send data packets of no more
than \fIn\fR bytes through the PPP network interface.
.TP
.B netmask \fI<n>
Set the interface netmask to <n>, a 32 bit netmask in "decimal dot"
notation (e.g. 255.255.255.0). If this option is given, the value
specified is ORed with the default netmask. The default netmask is
chosen based on the negotiated remote IP address; it is the
appropriate network mask for the class of the remote IP address, ORed
with the netmasks for any non point-to-point network interfaces in the
system which are on the same network.
.TP
.B passive
Enables the "passive" option in the LCP. With this option,
.I pppd
will attempt to initiate a connection; if no reply is received from
the peer,
.I pppd
will then just wait passively for a valid LCP packet from the peer
(instead of exiting, as it does without this option).
.TP
.B silent
With this option,
.I 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 \fIpppd\fR).
.SH OPTIONS
.TP
.I <local_IP_address>\fB:\fI<remote_IP_address>
Set the local and/or remote interface IP addresses. Either one may be
omitted. The IP addresses can be specified with a host name or in
decimal dot notation (e.g. 150.234.56.78). The default local
address is the (first) IP address of the system (unless the
.B noipdefault
option is given). The remote address will be obtained from the peer
if not specified in any option. Thus, in simple cases, this option is
not required. If a local and/or remote IP address is specified with
this option,
.I pppd
will not accept a different value from the peer in the IPCP
negotiation, unless the
.B ipcp-accept-local
and/or
.B ipcp-accept-remote
options are given, respectively.
.TP
.B -ac
Disable Address/Control compression negotiation (use default, i.e.
address/control field compression disabled).
.TP
.B -all
Don't request or allow negotiation of any options for LCP and IPCP (use
default values).
.TP
.B -am
Disable asyncmap negotiation (use the default asyncmap, i.e. escape
all control characters).
.TP
.B -as \fI<n>
Same as
.B asyncmap \fI<n>
.TP
.B bsdcomp \fInr,nt
Request that the peer compress packets that it sends, using the
BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and
agree to compress packets sent to the peer with a maximum code size of
\fInt\fR bits. If \fInt\fR is not specified, it defaults to the value
given for \fInr\fR. Values in the range 9 to 15 may be used for
\fInr\fR and \fInt\fR; larger values give better compression but
consume more kernel memory for compression dictionaries.
Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables
compression in the corresponding direction.
.TP
.B \-bsdcomp
Disables compression; \fBpppd\fR will not request or agree to compress
packets using the BSD-Compress scheme.
.TP
.B +chap
Require the peer to authenticate itself using CHAP [Cryptographic
Handshake Authentication Protocol] authentication.
.TP
.B -chap
Don't agree to authenticate using CHAP.
.TP
.B chap-interval \fI<n>
If this option is given,
.I pppd
will rechallenge the peer every <n> seconds.
.TP
.B chap-max-challenge \fI<n>
Set the maximum number of CHAP challenge transmissions to <n> (default
10).
.TP
.B chap-restart \fI<n>
Set the CHAP restart interval (retransmission timeout for challenges)
to <n> seconds (default 3).
.TP
.B -crtscts
Disable hardware flow control (i.e. RTS/CTS) on the serial port. If
neither the \fBcrtscts\fR nor the \fB\-crtscts\fR option is given,
the hardware flow control setting for the serial port is left
unchanged.
.TP
.B -d
Increase debugging level (same as the \fBdebug\fR option).
.TP
.B debug
Increase debugging level (same as \fB\-d\fR).
If this option is given, \fIpppd\fR will log the contents of all
control packets sent or received in a readable form. The packets are
logged through syslog with facility \fIdaemon\fR and level
\fIdebug\fR. This information can be directed to a file by setting up
/etc/syslog.conf appropriately (see syslog.conf(5)).
.TP
.B \-defaultroute
Disable the \fBdefaultroute\fR option. The system administrator who
wishes to prevent users from creating default routes with \fIpppd\fR
can do so by placing this option in the /etc/ppp/options file.
.TP
.B -detach
Don't fork to become a background process (otherwise
.I pppd
will do so if a serial device other than its controlling terminal is
specified).
.TP
.B dns-addr \fI<n>
This option sets the IP address or addresses for the Domain Name
Server. It is used by Microsoft Windows clients. The primary DNS
address is specified by the first instance of the dns-addr option. The
secondary is specified by the second instance.
.TP
.B domain \fI<d>
Append the domain name <d> to the local host name for authentication
purposes. For example, if gethostname() returns the name porsche, but the
fully qualified domain name is porsche.Quotron.COM, you would use the
domain option to set the domain name to Quotron.COM.
.TP
.B -ip
Disable IP address negotiation. If this option is used, the remote IP
address must be specified with an option on the command line or in an
options file.
.TP
.B +ip-protocol
Enable the IPCP and IP protocols. This is the default condition. This
option is only needed if the default setting is -ip-protocol.
.TP
.B -ip-protocol
Disable the IPCP and IP protocols. This should only be used if you
know that you are using a client which only understands IPX and you
don't want to confuse the client with the IPCP protocol.
.TP
.B +ipx-protocol
Enable the IPXCP and IPX protocols. This is the default condition if
your kernel supports IPX. This option is only needed if the default
setting is -ipx-protocol. If your kernel does not support IPX then this
option will have no effect.
.TP
.B -ipx-protocol
Disable the IPXCP and IPX protocols. This should only be used if you
know that you are using a client which only understands IP and you
don't want to confuse the client with the IPXCP protocol.
.TP
.B ipcp-accept-local
With this option,
.I pppd
will accept the peer's idea of our local IP address, even if the
local IP address was specified in an option.
.TP
.B ipcp-accept-remote
With this option,
.I pppd
will accept the peer's idea of its (remote) IP address, even if the
remote IP address was specified in an option.
.TP
.B ipcp-max-configure \fI<n>
Set the maximum number of IPCP configure-request transmissions to <n>
(default 10).
.TP
.B ipcp-max-failure \fI<n>
Set the maximum number of IPCP configure-NAKs returned before starting
to send configure-Rejects instead to <n> (default 10).
.TP
.B ipcp-max-terminate \fI<n>
Set the maximum number of IPCP terminate-request transmissions to <n>
(default 3).
.TP
.B ipcp-restart \fI<n>
Set the IPCP restart interval (retransmission timeout) to <n> seconds
(default 3).
.TP
.B ipparam \fIstring
Provides an extra parameter to the ip-up and ip-down scripts. If this
option is given, the \fIstring\fR supplied is given as the 6th
parameter to those scripts.
.TP
.B ipx-network \fI<n>
Set the IPX network number in the IPXCP configure request frame to
<n>. There is no valid default. If this option is not specified then
the network number is obtained from the peer. If the peer does not
have the network number, the IPX protocol will not be started. This is
a hexadecimal number and is entered without any leading sequence such
as 0x. It is related to the \fIipxcp-accept-network\fR option.
.TP
.B ipx-node \fI<n>:<m>
Set the IPX node numbers. The two node numbers are separated from each
other with a colon character. The first number <n> is the local node
number. The second number <m> is the peer's node number. Each node number
is a hexadecimal number, to the maximum of ten significant digits. The
node numbers on the ipx-network must be unique. There is no valid
default. If this option is not specified then the node number is
obtained from the peer. This option is a related to the
\fIipxcp-accept-local\fR and \fIipxcp-accept-remote\fR options.
.TP
.B ipx-router-name \fI<string>
Set the name of the router. This is a string and is sent to the peer
as information data.
.TP
.B ipx-routing \fI<n>
Set the routing protocol to be received by this option. More than one
instance of \fIipx-routing\fR may be specified. The '\fInone\fR'
option (0) may be specified as the only instance of ipx-routing. The
values may be \fI0\fR for \fINONE\fR, \fI2\fR for \fIRIP/SAP\fR, and
\fI4\fR for \fINLSP\fR.
.TP
.B ipxcp-accept-local
Accept the peer's NAK for the node number specified in the ipx-node
option. If a node number was specified, and non-zero, the default is
to insist that the value be used. If you include this option then you
will permit the peer to override the entry of the node number.
.TP
.B ipxcp-accept-network
Accept the peer's NAK for the network number specified in the
ipx-network option. If a network number was specified, and non-zero, the
default is to insist that the value be used. If you include this
option then you will permit the peer to override the entry of the node
number.
.TP
.B ipxcp-accept-remote
Use the peer's network number specified in the configure request
frame. If a node number was specified for the peer and this option was
not specified, the peer will be forced to use the value which you have
specified.
.TP
.B ipxcp-max-configure \fI<n>
Set the maximum number of IPXCP configure request frames which the
system will send to <n>. The default is 10.
.TP
.B ipxcp-max-failure \fI<n>
Set the maximum number of IPXCP NAK frames which the local system will
send before it rejects the options. The default value is 3.
.TP
.B ipxcp-max-terminate \fI<n>
Set the maximum nuber of IPXCP terminate request frames before the
local system considers that the peer is not listening to them. The
default value is 3.
.TP
.B kdebug \fIn
Enable debugging code in the kernel-level PPP driver. The argument
\fIn\fR is a number which is the sum of the following values: 1 to
enable general debug messages, 2 to request that the contents of
received packets be printed, and 4 to request that the contents of
transmitted packets be printed.
.TP
.B lcp-echo-failure \fI<n>
If this option is given, \fIpppd\fR will presume the peer to be dead
if \fIn\fR LCP echo-requests are sent without receiving a valid LCP
echo-reply. If this happens, \fIpppd\fR will terminate the
connection. Use of this option requires a non-zero value for the
\fIlcp-echo-interval\fR parameter. This option can be used to enable
\fIpppd\fR to terminate after the physical connection has been broken
(e.g., the modem has hung up) in situations where no hardware modem
control lines are available.
.TP
.B lcp-echo-interval \fI<n>
If this option is given, \fIpppd\fR will send an LCP echo-request
frame to the peer every \fIn\fR seconds. Under Linux, the
echo-request is sent when no packets have been received from the peer
for \fIn\fR seconds. Normally the peer should respond to the
echo-request by sending an echo-reply. This option can be used with
the \fIlcp-echo-failure\fR option to detect that the peer is no longer
connected.
.TP
.B lcp-max-configure \fI<n>
Set the maximum number of LCP configure-request transmissions to <n>
(default 10).
.TP
.B lcp-max-failure \fI<n>
Set the maximum number of LCP configure-NAKs returned before starting
to send configure-Rejects instead to <n> (default 10).
.TP
.B lcp-max-terminate \fI<n>
Set the maximum number of LCP terminate-request transmissions to <n>
(default 3).
.TP
.B lcp-restart \fI<n>
Set the LCP restart interval (retransmission timeout) to <n> seconds
(default 3).
.TP
.B local
Don't use the modem control lines. With this option,
.B pppd
will ignore the state of the CD (Carrier Detect) signal from the modem and
will not change the state of the DTR (Data Terminal Ready) signal.
.TP
.B login
Use the system password database for authenticating the peer using
PAP, and record the user in the system wtmp file.
.TP
.B modem
Use the modem control lines. This option is the default. With this
option,
.B pppd
will wait for the CD (Carrier Detect) signal from the modem to be asserted
when opening the serial device
(unless a connect script is specified), and it will drop the DTR (Data
Terminal Ready) signal briefly when the connection is terminated and before
executing the connect script.
On Ultrix, this option implies hardware
flow control, as for the \fBcrtscts\fR option.
.TP
.B -mn
Disable magic number negotiation. With this option,
.I pppd
cannot detect a looped-back line.
.TP
.B -mru
Disable MRU [Maximum Receive Unit] negotiation. With this option,
\fIpppd\fR will use the default MRU value of 1500 bytes.
.TP
.B name \fI<n>
Set the name of the local system for authentication purposes to <n>.
.TP
.B noipdefault
Disables the default behaviour when no local IP address is specified,
which is to determine (if possible) the local IP address from the
hostname. With this option, the peer will have to supply the local IP
address during IPCP negotiation (unless it specified explicitly on the
command line or in an options file).
.TP
.B -p
Same as the
.B passive
option.
.TP
.B +pap
Require the peer to authenticate itself using PAP.
.TP
.B -pap
Don't agree to authenticate using PAP.
.TP
.B papcrypt
Indicates that all secrets in the /etc/ppp/pap-secrets file which
are used for checking the identity of the peer are encrypted, and thus
pppd should not accept a password which (before encryption) is
identical to the secret from the /etc/ppp/pap-secrets file.
.TP
.B pap-max-authreq \fI<n>
Set the maximum number of PAP authenticate-request transmissions to
<n> (default 10).
.TP
.B pap-restart \fI<n>
Set the PAP restart interval (retransmission timeout) to <n> seconds
(default 3).
.TP
.B pap-timeout \fI<n>
Set the maximum time that
.I pppd
will wait for the peer to authenticate itself with PAP to
<n> seconds (0 means no limit).
.TP
.B -pc
Disable protocol field compression negotiation (use default, i.e.
protocol field compression disabled).
.TP
.B persist
Do not exit after a connection is terminated; instead try to reopen
the connection.
.TP
.B pred1comp
Attempt to request that the peer send the local system frames which
have been compressed by the Predictor-1 compression. The compression
protocols must be loaded or this option will be ignored.
.TP
.B -pred1comp
Do not accept Predictor-1 comprssion, even if the peer wants to send
this type of compression and support has been defined in the kernel.
.TP
.B proxyarp
Add an entry to this system's ARP [Address Resolution Protocol] table
with the IP address of the peer and the Ethernet address of this
system.
.TP
.B \-proxyarp
Disable the \fBproxyarp\fR option. The system administrator who
wishes to prevent users from creating proxy ARP entries with
\fIpppd\fR can do so by placing this option in the /etc/ppp/options
file.
.TP
.B remotename \fI<n>
Set the assumed name of the remote system for authentication purposes
to <n>.
.TP
.B +ua \fI<p>
Agree to authenticate using PAP [Password Authentication Protocol] if
requested by the peer, and
use the data in file <p> for the user and password to send to the
peer. The file contains the remote user name, followed by a newline,
followed by the remote password, followed by a newline. This option
is obsolescent.
.TP
.B usehostname
Enforce the use of the hostname as the name of the local system for
authentication purposes (overrides the
.B name
option).
.TP
.B user \fI<u>
Set the user name to use for authenticating this machine with the peer
using PAP to <u>.
.TP
.B -vj
Disable negotiation of Van Jacobson style TCP/IP header compression (use
default, i.e. no compression).
.TP
.B -vjccomp
Disable the connection-ID compression option in Van Jacobson style
TCP/IP header compression. With this option, \fIpppd\fR will not omit
the connection-ID byte from Van Jacobson compressed TCP/IP headers,
nor ask the peer to do so.
.TP
.B vj-max-slots \fIn
Sets the number of connection slots to be used by the Van Jacobson
TCP/IP header compression and decompression code to \fIn\fR, which
must be between 2 and 16 (inclusive).
.TP
.B xonxoff
Use software flow control (i.e. XON/XOFF) to control the flow of data on
the serial port. This option is only implemented on Linux systems
at present.
.SH OPTIONS FILES
Options can be taken from files as well as the command line.
.I pppd
reads options from the files /etc/ppp/options and ~/.ppprc before
looking at the command line. An options file is parsed into a series
of words, delimited by whitespace. Whitespace can be included in a
word by enclosing the word in quotes ("). A backslash (\\) quotes the
following character. A hash (#) starts a comment, which continues
until the end of the line.
.SH AUTHENTICATION
.I pppd
provides system administrators with sufficient access control that PPP
access to a server machine can be provided to legitimate users without
fear of compromising the security of the server or the network it's
on. In part this is provided by the /etc/ppp/options file, where the
administrator can place options to require authentication whenever
.I pppd
is run, and in part by the PAP and CHAP secrets files, where the
administrator can restrict the set of IP addresses which individual
users may use.
.LP
The default behaviour of
.I pppd
is to agree to authenticate if requested, and to not
require authentication from the peer. However,
.I pppd
will not agree to
authenticate itself with a particular protocol if it has no secrets
which could be used to do so.
.LP
Authentication is based on secrets, which are selected from secrets
files (/etc/ppp/pap-secrets for PAP, /etc/ppp/chap-secrets for CHAP).
Both secrets files have the same format, and both can store secrets
for several combinations of server (authenticating peer) and client
(peer being authenticated). Note that
.I pppd
can be both a server
and client, and that different protocols can be used in the two
directions if desired.
.LP
A secrets file is parsed into words as for a options file. A secret
is specified by a line containing at least 3 words, in the order
client name, server name, secret. Any following words on the same line are
taken to be a list of acceptable IP addresses for that client. If
there are only 3 words on the line, it is assumed that any IP address
is OK; to disallow all IP addresses, use "-". If the secret starts
with an `@', what follows is assumed to be the name of a file from
which to read the secret. A "*" as the client or server name matches
any name. When selecting a secret, \fIpppd\fR takes the best match, i.e.
the match with the fewest wildcards.
.LP
Thus a secrets file contains both secrets for use in authenticating
other hosts, plus secrets which we use for authenticating ourselves to
others. Which secret to use is chosen based on the names of the host
(the `local name') and its peer (the `remote name'). The local name
is set as follows:
.TP 3
if the \fBusehostname\fR option is given,
then the local name is the hostname of this machine
(with the domain appended, if given)
.TP 3
else if the \fBname\fR option is given,
then use the argument of the first \fBname\fR option seen
.TP 3
else if the local IP address is specified with a hostname,
then use that name
.TP 3
else use the hostname of this machine (with the domain appended, if given)
.LP
When authenticating ourselves using PAP, there is also a `username'
which is the local name by default, but can be set with the \fBuser\fR
option or the \fB+ua\fR option.
.LP
The remote name is set as follows:
.TP 3
if the \fBremotename\fR option is given,
then use the argument of the last \fBremotename\fR option seen
.TP 3
else if the remote IP address is specified with a hostname,
then use that host name
.TP 3
else the remote name is the null string "".
.LP
Secrets are selected from the PAP secrets file as follows:
.TP 2
*
For authenticating the peer, look for a secret with client ==
username specified in the PAP authenticate-request, and server ==
local name.
.TP 2
*
For authenticating ourselves to the peer, look for a secret with
client == our username, server == remote name.
.LP
When authenticating the peer with PAP, a secret of "" matches any
password supplied by the peer. If the password doesn't match the
secret, the password is encrypted using crypt() and checked against
the secret again; thus secrets for authenticating the peer can be
stored in encrypted form. If the \fBpapcrypt\fR option is given, the
first (unencrypted) comparison is omitted, for better security.
.LP
If the \fBlogin\fR option was specified, the
username and password are also checked against the system password
database. Thus, the system administrator can set up the pap-secrets
file to allow PPP access only to certain users, and to restrict the
set of IP addresses that each user can use. Typically, when using the
\fBlogin\fR option, the secret in /etc/ppp/pap-secrets would be "", to
avoid the need to have the same secret in two places.
.LP
Secrets are selected from the CHAP secrets file as follows:
.TP 2
*
For authenticating the peer, look for a secret with client == name
specified in the CHAP-Response message, and server == local name.
.TP 2
*
For authenticating ourselves to the peer, look for a secret with
client == local name, and server == name specified in the
CHAP-Challenge message.
.LP
Authentication must be satisfactorily completed before IPCP (or any
other Network Control Protocol) can be started. If authentication
fails, \fIpppd\fR will terminated the link (by closing LCP). If IPCP
negotiates an unacceptable IP address for the remote host, IPCP will
be closed. IP packets can only be sent or received when IPCP is open.
.LP
In some cases it is desirable to allow some hosts which can't
authenticate themselves to connect and use one of a restricted set of
IP addresses, even when the local host generally requires
authentication. If the peer refuses to authenticate itself when
requested, \fIpppd\fR takes that as equivalent to authenticating with
PAP using the empty string for the username and password. Thus, by
adding a line to the pap-secrets file which specifies the empty string
for the client and password, it is possible to allow restricted access
to hosts which refuse to authenticate themselves.
.SH ROUTING
.LP
When IPCP negotiation is completed successfully,
.I pppd
will inform the kernel of the local and remote IP addresses for the
ppp interface. This is sufficient to create a
host route to the remote end of the link, which will enable the peers
to exchange IP packets. Communication with other machines generally
requires further modification to routing tables and/or ARP (Address
Resolution Protocol) tables. In some cases this will be done
automatically through the actions of the \fIrouted\fR or \fIgated\fR
daemons, but in most cases some further intervention is required.
.LP
Sometimes it is desirable
to add a default route through the remote host, as in the case of a
machine whose only connection to the Internet is through the ppp
interface. The \fBdefaultroute\fR option causes \fIpppd\fR to create such a
default route when IPCP comes up, and delete it when the link is
terminated.
.LP
In some cases it is desirable to use proxy ARP, for example on a
server machine connected to a LAN, in order to allow other hosts to
communicate with the remote host. The \fBproxyarp\fR option causes \fIpppd\fR
to look for a network interface on the same subnet as the remote host
(an interface supporting broadcast and ARP, which is up and not a
point-to-point or loopback interface). If found, \fIpppd\fR creates a
permanent, published ARP entry with the IP address of the remote host
and the hardware address of the network interface found.
.SH EXAMPLES
.LP
In the simplest case, you can connect the serial ports of two machines
and issue a command like
.IP
pppd /dev/ttya 9600 passive
.LP
to each machine, assuming there is no \fIgetty\fR running on the
serial ports. If one machine has a \fIgetty\fR running, you can use
\fIkermit\fR or \fItip\fR on the other machine to log in to the first
machine and issue a command like
.IP
pppd passive
.LP
Then exit from the communications program (making sure the connection
isn't dropped), and issue a command like
.IP
pppd /dev/ttya 9600
.LP
The process of logging in to the other machine and starting \fIpppd\fR
can be automated by using the \fBconnect\fR option to run \fIchat\fR,
for example:
.IP
pppd /dev/ttya 38400 connect 'chat "" "" "login:" "username"
"Password:" "password" "% " "exec pppd passive"'
.LP
(Note however that running chat like this will leave the password
visible in the parameter list of pppd and chat.)
.LP
If your serial connection is any more complicated than a piece of
wire, you may need to arrange for some control characters to be
escaped. In particular, it is often useful to escape XON (^Q) and
XOFF (^S), using \fBasyncmap a0000\fR. If the path includes a telnet,
you probably should escape ^] as well (\fBasyncmap 200a0000\fR).
If the path includes an rlogin, you will need to use the \fBescape
ff\fR option on the end which is running the rlogin client, since many
rlogin implementations are not
transparent; they will remove the sequence [0xff, 0xff, 0x73, 0x73,
followed by any 8 bytes] from the stream.
.SH DIAGNOSTICS
.LP
Messages are sent to the syslog daemon using facility LOG_DAEMON.
(This can be overriden by recompiling \fIpppd\fR with the macro
LOG_PPP defined as the desired facility.) In order to see the error
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 \fBdebug\fR option causes the contents of all control packets sent
or received to be logged, that is, all LCP, PAP, CHAP or IPCP packets.
This can be useful if the PPP negotiation does not succeed.
If debugging is enabled at compile time, the \fBdebug\fR option also
causes other debugging messages to be logged.
.LP
Debugging can also be enabled or disabled by sending a
SIGUSR1 to the
.I pppd
process. This signal acts as a toggle.
.SH FILES
.TP
.B /var/run/ppp\fIn\fB.pid \fR(BSD or Linux), \fB/etc/ppp/ppp\fIn\fB.pid \fR(others)
Process-ID for \fIpppd\fR process on ppp interface unit \fIn\fR.
.TP
.B /etc/ppp/ip-up
A program or script which is executed when the link is available for
sending and receiving IP packets (that is, IPCP has come up). It is
executed with the parameters
.IP
\fIinterface-name tty-device speed local-IP-address
remote-IP-address\fR
.IP
and with its standard input,
output and error streams redirected to \fB/dev/null\fR.
.IP
This program or script is executed with the same real and effective
user-ID as \fIpppd\fR, that is, at least the effective user-ID and
possibly the real user-ID will be \fBroot\fR. This is so that it can
be used to manipulate routes, run privileged daemons (e.g.
\fBsendmail\fR), etc. Be careful that the contents of the
/etc/ppp/ip-up and /etc/ppp/ip-down scripts do not compromise your
system's security.
.TP
.B /etc/ppp/ip-down
A program or script which is executed when the link is no longer
available for sending and receiving IP packets. This script can be
used for undoing the effects of the /etc/ppp/ip-up script. It is
invoked with the same parameters as the ip-up script, and the same
security considerations apply, since it is executed with the same
effective and real user-IDs as \fIpppd\fR.
.TP
.B /etc/ppp/ipx-up
A program or script which is executed when the link is available for
sending and receiving IPX packets (that is, IPXCP has come up). It is
executed with the parameters
.IP
\fIinterface-name tty-device speed network-number local-IPX-node-address
remote-IPX-node-address local-IPX-routing-protocol remote-IPX-routing-protocol
local-IPX-router-name remote-IPX-router-name ipparam pppd-pid\fR
.IP
and with its standard input,
output and error streams redirected to \fB/dev/null\fR.
.br
.IP
The local-IPX-routing-protocol and remote-IPX-routing-protocol field
may be one of the following:
.IP
NONE to indicate that there is no routing protocol
.br
RIP to indicate that RIP/SAP should be used
.br
NLSP to indicate that Novell NLSP should be used
.br
RIP NLSP to indicate that both RIP/SAP and NLSP should be used
.br
.IP
This program or script is executed with the same real and effective
user-ID as \fIpppd\fR, that is, at least the effective user-ID and
possibly the real user-ID will be \fBroot\fR. This is so that it can
be used to manipulate routes, run privileged daemons (e.g.
\fBripd\fR), etc. Be careful that the contents of the
/etc/ppp/ipx-up and /etc/ppp/ipx-down scripts do not compromise your
system's security.
.TP
.B /etc/ppp/ipx-down
A program or script which is executed when the link is no longer
available for sending and receiving IPX packets. This script can be
used for undoing the effects of the /etc/ppp/ipx-up script. It is
invoked with the same parameters as the ipx-up script, and the same
security considerations apply, since it is executed with the same
effective and real user-IDs as \fIpppd\fR.
.TP
.B /etc/ppp/pap-secrets
Usernames, passwords and IP addresses for PAP authentication.
.TP
.B /etc/ppp/chap-secrets
Names, secrets and IP addresses for CHAP authentication.
.TP
.B /etc/ppp/options
System default options for
.I pppd,
read before user default options or command-line options.
.TP
.B ~/.ppprc
User default options, read before command-line options.
.TP
.B /etc/ppp/options.\fIttyname
System default options for the serial port being used, read after
command-line options.
.SH SEE ALSO
.TP
.B RFC1144
Jacobson, V.
.I Compressing TCP/IP headers for low-speed serial links.
1990 February.
.TP
.B RFC1321
Rivest, R.
.I The MD5 Message-Digest Algorithm.
1992 April.
.TP
.B RFC1332
McGregor, G.
.I PPP Internet Protocol Control Protocol (IPCP).
1992 May.
.TP
.B RFC1334
Lloyd, B.; Simpson, W.A.
.I PPP authentication protocols.
1992 October.
.TP
.B RFC1548
Simpson, W.A.
.I The Point\-to\-Point Protocol (PPP).
1993 December.
.TP
.B RFC1549
Simpson, W.A.
.I PPP in HDLC Framing.
1993 December
.SH NOTES
The following signals have the specified effect when sent to the
.I pppd
process.
.TP
.B SIGINT, SIGTERM
These signals cause \fBpppd\fR to terminate the link (by closing LCP),
restore the serial device settings, and exit.
.TP
.B SIGHUP
This signal causes \fBpppd\fR to terminate the link, restore the
serial device settings, and close the serial device. If the
\fBpersist\fR option has been specified, \fBpppd\fR will try to reopen
the serial device and start another connection. Otherwise \fBpppd\fR
will exit.
.TP
.B SIGUSR2
This signal causes
.B pppd
to renegotiate compression. This can be useful to re-enable
compression after it has been disabled as a result of a fatal
decompression error. With the BSD Compress scheme, fatal
decompression errors generally indicate a bug in one or other
implementation.
.SH AUTHORS
Drew Perkins,
Brad Clements,
Karl Fox,
Greg Christy,
Brad Parker,
Paul Mackerras (paulus@cs.anu.edu.au).

1374
ipppd/ipxcp.c Normal file

File diff suppressed because it is too large Load Diff

68
ipppd/ipxcp.h Normal file
View File

@ -0,0 +1,68 @@
/*
* ipxcp.h - IPX Control Protocol definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id: ipxcp.h,v 1.1 1997/03/07 16:01:22 hipp Exp $
*/
/*
* Options.
*/
#define IPX_NETWORK_NUMBER 1 /* IPX Network Number */
#define IPX_NODE_NUMBER 2
#define IPX_COMPRESSION_PROTOCOL 3
#define IPX_ROUTER_PROTOCOL 4
#define IPX_ROUTER_NAME 5
#define IPX_COMPLETE 6
typedef struct ipxcp_options {
int neg_node : 1; /* Negotiate IPX node number? */
int req_node : 1; /* Ask peer to send IPX node number? */
int neg_nn : 1; /* Negotiate IPX network number? */
int req_nn : 1; /* Ask peer to send IPX network number */
int neg_name : 1; /* Negotiate IPX router name */
int neg_complete : 1; /* Negotiate completion */
int neg_router : 1; /* Negotiate IPX router number */
int accept_local : 1; /* accept peer's value for ournode */
int accept_remote : 1; /* accept peer's value for hisnode */
int accept_network : 1; /* accept network number */
u_int32_t his_network; /* base network number */
u_int32_t our_network; /* our value for network number */
u_int32_t network; /* the final network number */
u_char his_node[6]; /* peer's node number */
u_char our_node[6]; /* our node number */
u_char name [48]; /* name of the router */
int router; /* routing protocol */
} ipxcp_options;
extern fsm ipxcp_fsm[];
extern ipxcp_options ipxcp_wantoptions[];
extern ipxcp_options ipxcp_gotoptions[];
extern ipxcp_options ipxcp_allowoptions[];
extern ipxcp_options ipxcp_hisoptions[];
extern struct protent ipxcp_protent;
int ipxcp_getunit __P((int));
void ipxcp_freeunit __P((int));

111
ipppd/isexpired.c Normal file
View File

@ -0,0 +1,111 @@
/*
* Copyright 1989 - 1994, John F. Haugh II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by John F. Haugh, II
* and other contributors.
* 4. Neither the name of John F. Haugh, II nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JOHN HAUGH AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL JOHN HAUGH OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Extracted from age.c and made part of libshadow.a - may be useful
* in other shadow-aware programs. --marekm
*/
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#ifndef BSD
#include <sys/wait.h>
#endif
#include <shadow.h>
#define DAY (24L*3600L)
#define SCALE DAY
extern time_t time ();
/*
* isexpired - determine if account is expired yet
*
* isexpired calculates the expiration date based on the
* password expiration criteria.
*/
/*ARGSUSED*/
int
isexpired (pw, sp)
const struct passwd *pw;
const struct spwd *sp;
{
long now;
now = time ((time_t *) 0) / SCALE;
/*
* Quick and easy - there is an expired account field
* along with an inactive account field. Do the expired
* one first since it is worse.
*/
if (sp->sp_expire > 0 && sp->sp_expire < now)
return 3;
/*
* Hack: last changed date 1970-01-01 (not very likely) means that
* the password must be changed as soon as possible. This is used
* by passwd -e (SunOS 4.x has a similar feature). --marekm
*/
if (sp->sp_lstchg == 0)
return 1;
if (sp->sp_inact > 0 && sp->sp_lstchg > 0 && sp->sp_max > 0 &&
sp->sp_inact + sp->sp_lstchg + sp->sp_max < now)
return 2;
/*
* The last and max fields must be present for an account
* to have an expired password. A maximum of >10000 days
* is considered to be infinite.
*/
if (sp->sp_lstchg == -1 ||
sp->sp_max == -1 || sp->sp_max >= (10000L*DAY/SCALE))
return 0;
/*
* Calculate today's day and the day on which the password
* is going to expire. If that date has already passed,
* the password has expired.
*/
if (sp->sp_lstchg + sp->sp_max < now)
return 1;
return 0;
}

2150
ipppd/lcp.c Normal file

File diff suppressed because it is too large Load Diff

114
ipppd/lcp.h Normal file
View File

@ -0,0 +1,114 @@
/*
* lcp.h - Link Control Protocol definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id: lcp.h,v 1.1 1997/03/07 16:01:27 hipp Exp $
*/
/*
* Options.
*/
#define CI_MRU 1 /* Maximum Receive Unit */
#define CI_ASYNCMAP 2 /* Async Control Character Map */
#define CI_AUTHTYPE 3 /* Authentication Type */
#define CI_QUALITY 4 /* Quality Protocol */
#define CI_MAGICNUMBER 5 /* Magic Number */
#define CI_PCOMPRESSION 7 /* Protocol Field Compression */
#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
#define CI_CALLBACK 13 /* callback */
#define CI_MPMRRU 17
#define CI_MPSHORTSEQ 18
#define CI_MPDISCRIMINATOR 19
/*
* LCP-specific packet types.
*/
#define PROTREJ 8 /* Protocol Reject */
#define ECHOREQ 9 /* Echo Request */
#define ECHOREP 10 /* Echo Reply */
#define DISCREQ 11 /* Discard Request */
#define CBCP_OPT 6
struct cbcp {
int type;
unsigned char *message;
int mlen;
};
/*
* The state of options is described by an lcp_options structure.
*/
typedef struct lcp_options {
int passive : 1; /* Don't die if we don't get a response */
int silent : 1; /* Wait for the other end to start first */
int restart : 1; /* Restart vs. exit after close */
int neg_mru : 1; /* Negotiate the MRU? */
int neg_asyncmap : 1; /* Negotiate the async map? */
int neg_upap : 1; /* Ask for UPAP authentication? */
int neg_chap : 1; /* Ask for CHAP authentication? */
int neg_magicnumber : 1; /* Ask for magic number? */
int neg_pcompression : 1; /* HDLC Protocol Field Compression? */
int neg_accompression : 1; /* HDLC Address/Control Field Compression? */
int neg_lqr : 1; /* Negotiate use of Link Quality Reports */
int neg_mpshortseq : 1; /* MP 12 bit instead of 24 bit sequence numbers */
int neg_mpdiscr : 1; /* MP protocol ? */
int neg_mpmrru : 1;
int neg_mp : 1;
int neg_cbcp : 1;
u_char mp_class; /* MP discri. class */
u_char mp_addr[20]; /* MP discri. addr */
u_char mp_alen;
u_short mp_mrru; /* MP mrru */
u_char cb_type;
u_char cb_num[20];
u_char cb_numlen;
u_short mru; /* Value of MRU */
u_char chap_mdtype; /* which MD type (hashing algorithm) */
u_int32_t asyncmap; /* Value of async map */
u_int32_t magicnumber;
int numloops; /* Number of loops during magic number neg. */
u_int32_t lqr_period; /* Reporting period for LQR 1/100ths second */
struct cbcp cbcp;
} lcp_options;
extern fsm lcp_fsm[];
extern lcp_options lcp_wantoptions[];
extern lcp_options lcp_gotoptions[];
extern lcp_options lcp_allowoptions[];
extern lcp_options lcp_hisoptions[];
extern u_int32_t xmit_accm[][8];
extern struct protent lcp_protent;
#define DEFMRU 1500 /* Try for this */
#define MINMRU 128 /* No MRUs below this */
#define MAXMRU 16384 /* Normally limit MRU to this */
void lcp_open __P((int));
void lcp_close __P((int,char *));
void lcp_lowerup __P((int));
void lcp_lowerdown __P((int));
void lcp_sprotrej __P((int, u_char *, int));
/* Default number of times we receive our magic number from the peer
before deciding the link is looped-back. */
#define DEFLOOPBACKFAIL 5

118
ipppd/magic.c Normal file
View File

@ -0,0 +1,118 @@
/*
* magic.c - PPP Magic Number routines.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*/
#if 0
#ifndef lint
static char rcsid[] = "$Id: magic.c,v 1.1 1997/03/07 16:01:27 hipp Exp $";
#endif
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/utsname.h>
#include "fsm.h"
#include "pppd.h"
#include "magic.h"
#if 0
static u_int32_t next; /* Next value to return */
#endif
extern long mrand48 __P((void));
extern void srand48 __P((long));
/*
* magic_init - Initialize the magic number generator.
*
* Attempts to compute a random number seed which will not repeat.
* The current method uses the current hostid, current process ID
* and current time, currently.
*/
void
magic_init()
{
long seed;
struct timeval t;
struct utsname uts;
unsigned long val=0x12345678;
int i;
gettimeofday(&t, NULL);
if(uname(&uts)==0) {
unsigned char *p = (unsigned char *) &uts;
int len = sizeof(struct utsname);
int step=47;
if(len % step == 0) /* unlikely, but ;) */
step = 43;
for(i=0;i<len;i++) {
if(val & 0x80000000)
val = ( (val<<1) + p[ (i*step)%len ]) + 1;
else
val = ( (val<<1) + p[ (i*step)%len ]);
val &= 0xffffffff;
}
}
else
val = gethostid();
seed = val ^ t.tv_sec ^ t.tv_usec ^ getpid();
srand48(seed);
}
/*
* magic - Returns the next magic number.
*/
u_int32_t
magic(void)
{
return (u_int32_t) mrand48();
}
#ifdef NO_DRAND48
/*
* Substitute procedures for those systems which don't have
* drand48 et al.
*/
double
drand48()
{
return (double)random() / (double)0x7fffffffL; /* 2**31-1 */
}
long
mrand48()
{
return random();
}
void
srand48(seedval)
long seedval;
{
srandom((int)seedval);
}
#endif

23
ipppd/magic.h Normal file
View File

@ -0,0 +1,23 @@
/*
* magic.h - PPP Magic Number definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id: magic.h,v 1.1 1997/03/07 16:01:28 hipp Exp $
*/
void magic_init __P((void)); /* Initialize the magic number generator */
u_int32_t magic __P((void)); /* Returns the next magic number */

1402
ipppd/main.c Normal file

File diff suppressed because it is too large Load Diff

297
ipppd/md4.c Normal file
View File

@ -0,0 +1,297 @@
/*
** ********************************************************************
** md4.c -- Implementation of MD4 Message Digest Algorithm **
** Updated: 2/16/90 by Ronald L. Rivest **
** (C) 1990 RSA Data Security, Inc. **
** ********************************************************************
*/
/*
** To use MD4:
** -- Include md4.h in your program
** -- Declare an MDstruct MD to hold the state of the digest
** computation.
** -- Initialize MD using MDbegin(&MD)
** -- For each full block (64 bytes) X you wish to process, call
** MDupdate(&MD,X,512)
** (512 is the number of bits in a full block.)
** -- For the last block (less than 64 bytes) you wish to process,
** MDupdate(&MD,X,n)
** where n is the number of bits in the partial block. A partial
** block terminates the computation, so every MD computation
** should terminate by processing a partial block, even if it
** has n = 0.
** -- The message digest is available in MD.buffer[0] ...
** MD.buffer[3]. (Least-significant byte of each word
** should be output first.)
** -- You can print out the digest using MDprint(&MD)
*/
/* Implementation notes:
** This implementation assumes that ints are 32-bit quantities.
** If the machine stores the least-significant byte of an int in the
** least-addressed byte (e.g., VAX and 8086), then LOWBYTEFIRST
** should be set to TRUE. Otherwise (e.g., SUNS), LOWBYTEFIRST
** should be set to FALSE. Note that on machines with LOWBYTEFIRST
** FALSE the routine MDupdate modifies has a side-effect on its input
** array (the order of bytes in each word are reversed). If this is
** undesired a call to MDreverse(X) can reverse the bytes of X back
** into order after each call to MDupdate.
**
** NOTE: LOWBYTEFIRST removed by Eric Rosenquist in favour of run-time
** detection to simplify build process.
*/
#define TRUE 1
#define FALSE 0
/* Compile-time includes
*/
#include <stdio.h>
#include <netinet/in.h>
#include "md4.h"
#include "pppd.h"
/* Compile-time declarations of MD4 "magic constants".
*/
#define I0 0x67452301 /* Initial values for MD buffer */
#define I1 0xefcdab89
#define I2 0x98badcfe
#define I3 0x10325476
#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
** Table 2, page 660.
*/
#define fs1 3 /* round 1 shift amounts */
#define fs2 7
#define fs3 11
#define fs4 19
#define gs1 3 /* round 2 shift amounts */
#define gs2 5
#define gs3 9
#define gs4 13
#define hs1 3 /* round 3 shift amounts */
#define hs2 9
#define hs3 11
#define hs4 15
/* Compile-time macro declarations for MD4.
** Note: The "rot" operator uses the variable "tmp".
** It assumes tmp is declared as unsigned int, so that the >>
** operator will shift in zeros rather than extending the sign bit.
*/
#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
#define h(X,Y,Z) (X^Y^Z)
#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
/* MDprint(MDp)
** Print message digest buffer MDp as 32 hexadecimal digits.
** Order is from low-order byte of buffer[0] to high-order byte of
** buffer[3].
** Each byte is printed with high-order hexadecimal digit first.
** This is a user-callable routine.
*/
void
MDprint(MDp)
MDptr MDp;
{ int i,j;
for (i=0;i<4;i++)
for (j=0;j<32;j=j+8)
printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
}
/* MDbegin(MDp)
** Initialize message digest buffer MDp.
** This is a user-callable routine.
*/
void
MDbegin(MDp)
MDptr MDp;
{ int i;
MDp->buffer[0] = I0;
MDp->buffer[1] = I1;
MDp->buffer[2] = I2;
MDp->buffer[3] = I3;
for (i=0;i<8;i++) MDp->count[i] = 0;
MDp->done = 0;
}
/* MDreverse(X)
** Reverse the byte-ordering of every int in X.
** Assumes X is an array of 16 ints.
** The macro revx reverses the byte-ordering of the next word of X.
*/
#define revx { t = (*X << 16) | (*X >> 16); \
*X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); }
void
MDreverse(X)
unsigned int *X;
{ register unsigned int t;
revx; revx; revx; revx; revx; revx; revx; revx;
revx; revx; revx; revx; revx; revx; revx; revx;
}
/* MDblock(MDp,X)
** Update message digest buffer MDp->buffer using 16-word data block X.
** Assumes all 16 words of X are full of data.
** Does not update MDp->count.
** This routine is not user-callable.
*/
static void
MDblock(MDp,X)
MDptr MDp;
unsigned int *X;
{
register unsigned int tmp, A, B, C, D;
static int low_byte_first = -1;
if (low_byte_first == -1) {
low_byte_first = (htons((unsigned short int)1) != 1);
}
if (low_byte_first == 0) {
MDreverse(X);
}
A = MDp->buffer[0];
B = MDp->buffer[1];
C = MDp->buffer[2];
D = MDp->buffer[3];
/* Update the message digest buffer */
ff(A , B , C , D , 0 , fs1); /* Round 1 */
ff(D , A , B , C , 1 , fs2);
ff(C , D , A , B , 2 , fs3);
ff(B , C , D , A , 3 , fs4);
ff(A , B , C , D , 4 , fs1);
ff(D , A , B , C , 5 , fs2);
ff(C , D , A , B , 6 , fs3);
ff(B , C , D , A , 7 , fs4);
ff(A , B , C , D , 8 , fs1);
ff(D , A , B , C , 9 , fs2);
ff(C , D , A , B , 10 , fs3);
ff(B , C , D , A , 11 , fs4);
ff(A , B , C , D , 12 , fs1);
ff(D , A , B , C , 13 , fs2);
ff(C , D , A , B , 14 , fs3);
ff(B , C , D , A , 15 , fs4);
gg(A , B , C , D , 0 , gs1); /* Round 2 */
gg(D , A , B , C , 4 , gs2);
gg(C , D , A , B , 8 , gs3);
gg(B , C , D , A , 12 , gs4);
gg(A , B , C , D , 1 , gs1);
gg(D , A , B , C , 5 , gs2);
gg(C , D , A , B , 9 , gs3);
gg(B , C , D , A , 13 , gs4);
gg(A , B , C , D , 2 , gs1);
gg(D , A , B , C , 6 , gs2);
gg(C , D , A , B , 10 , gs3);
gg(B , C , D , A , 14 , gs4);
gg(A , B , C , D , 3 , gs1);
gg(D , A , B , C , 7 , gs2);
gg(C , D , A , B , 11 , gs3);
gg(B , C , D , A , 15 , gs4);
hh(A , B , C , D , 0 , hs1); /* Round 3 */
hh(D , A , B , C , 8 , hs2);
hh(C , D , A , B , 4 , hs3);
hh(B , C , D , A , 12 , hs4);
hh(A , B , C , D , 2 , hs1);
hh(D , A , B , C , 10 , hs2);
hh(C , D , A , B , 6 , hs3);
hh(B , C , D , A , 14 , hs4);
hh(A , B , C , D , 1 , hs1);
hh(D , A , B , C , 9 , hs2);
hh(C , D , A , B , 5 , hs3);
hh(B , C , D , A , 13 , hs4);
hh(A , B , C , D , 3 , hs1);
hh(D , A , B , C , 11 , hs2);
hh(C , D , A , B , 7 , hs3);
hh(B , C , D , A , 15 , hs4);
MDp->buffer[0] += A;
MDp->buffer[1] += B;
MDp->buffer[2] += C;
MDp->buffer[3] += D;
}
/* MDupdate(MDp,X,count)
** Input: MDp -- an MDptr
** X -- a pointer to an array of unsigned characters.
** count -- the number of bits of X to use.
** (if not a multiple of 8, uses high bits of last byte.)
** Update MDp using the number of bits of X given by count.
** This is the basic input routine for an MD4 user.
** The routine completes the MD computation when count < 512, so
** every MD computation should end with one call to MDupdate with a
** count less than 512. A call with count 0 will be ignored if the
** MD has already been terminated (done != 0), so an extra call with
** count 0 can be given as a "courtesy close" to force termination
** if desired.
*/
void
MDupdate(MDp,X,count)
MDptr MDp;
unsigned char *X;
unsigned int count;
{ unsigned int i, tmp, bit, byte, mask;
unsigned char XX[64];
unsigned char *p;
/* return with no error if this is a courtesy close with count
** zero and MDp->done is true.
*/
if (count == 0 && MDp->done) return;
/* check to see if MD is already done and report error */
if (MDp->done)
{ printf("\nError: MDupdate MD already done."); return; }
/* Add count to MDp->count */
tmp = count;
p = MDp->count;
while (tmp)
{ tmp += *p;
*p++ = tmp;
tmp = tmp >> 8;
}
/* Process data */
if (count == 512)
{ /* Full block of data to handle */
MDblock(MDp,(unsigned int *)X);
}
else if (count > 512) /* Check for count too large */
{ printf("\nError: MDupdate called with illegal count value %d."
,count);
return;
}
else /* partial block -- must be last block so finish up */
{ /* Find out how many bytes and residual bits there are */
byte = count >> 3;
bit = count & 7;
/* Copy X into XX since we need to modify it */
for (i=0;i<=byte;i++) XX[i] = X[i];
for (i=byte+1;i<64;i++) XX[i] = 0;
/* Add padding '1' bit and low-order zeros in last byte */
mask = 1 << (7 - bit);
XX[byte] = (XX[byte] | mask) & ~( mask - 1);
/* If room for bit count, finish up with this block */
if (byte <= 55)
{ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
MDblock(MDp,(unsigned int *)XX);
}
else /* need to do two blocks to finish up */
{ MDblock(MDp,(unsigned int *)XX);
for (i=0;i<56;i++) XX[i] = 0;
for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
MDblock(MDp,(unsigned int *)XX);
}
/* Set flag saying we're done with MD computation */
MDp->done = 1;
}
}
/*
** End of md4.c
****************************(cut)***********************************/

51
ipppd/md4.h Normal file
View File

@ -0,0 +1,51 @@
/*
** ********************************************************************
** md4.h -- Header file for implementation of **
** MD4 Message Digest Algorithm **
** Updated: 2/13/90 by Ronald L. Rivest **
** (C) 1990 RSA Data Security, Inc. **
** ********************************************************************
*/
/* MDstruct is the data structure for a message digest computation.
*/
typedef struct {
unsigned int buffer[4]; /* Holds 4-word result of MD computation */
unsigned char count[8]; /* Number of bits processed so far */
unsigned int done; /* Nonzero means MD computation finished */
} MDstruct, *MDptr;
/* MDbegin(MD)
** Input: MD -- an MDptr
** Initialize the MDstruct prepatory to doing a message digest
** computation.
*/
extern void MDbegin();
/* MDupdate(MD,X,count)
** Input: MD -- an MDptr
** X -- a pointer to an array of unsigned characters.
** count -- the number of bits of X to use (an unsigned int).
** Updates MD using the first "count" bits of X.
** The array pointed to by X is not modified.
** If count is not a multiple of 8, MDupdate uses high bits of
** last byte.
** This is the basic input routine for a user.
** The routine terminates the MD computation when count < 512, so
** every MD computation should end with one call to MDupdate with a
** count less than 512. Zero is OK for a count.
*/
extern void MDupdate();
/* MDprint(MD)
** Input: MD -- an MDptr
** Prints message digest buffer MD as 32 hexadecimal digits.
** Order is from low-order byte of buffer[0] to high-order byte
** of buffer[3].
** Each byte is printed with high-order hexadecimal digit first.
*/
extern void MDprint();
/*
** End of md4.h
****************************(cut)***********************************/

304
ipppd/md5.c Normal file
View File

@ -0,0 +1,304 @@
/*
***********************************************************************
** md5.c -- the source code for MD5 routines **
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
***********************************************************************
*/
/*
***********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
***********************************************************************
*/
#include "md5.h"
/*
***********************************************************************
** Message-digest routines: **
** To form the message digest for a message M **
** (1) Initialize a context buffer mdContext using MD5Init **
** (2) Call MD5Update on mdContext and M **
** (3) Call MD5Final on mdContext **
** The message digest is now in mdContext->digest[0...15] **
***********************************************************************
*/
/* forward declaration */
static void Transform ();
static unsigned char PADDING[64] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* F, G, H and I are basic MD5 functions */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s, ac) \
{(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) \
{(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) \
{(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) \
{(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#ifdef __STDC__
#define UL(x) x##U
#else
#define UL(x) x
#endif
/* The routine MD5Init initializes the message-digest context
mdContext. All fields are set to zero.
*/
void MD5Init (mdContext)
MD5_CTX *mdContext;
{
mdContext->i[0] = mdContext->i[1] = (UINT4)0;
/* Load magic initialization constants.
*/
mdContext->buf[0] = (UINT4)0x67452301;
mdContext->buf[1] = (UINT4)0xefcdab89;
mdContext->buf[2] = (UINT4)0x98badcfe;
mdContext->buf[3] = (UINT4)0x10325476;
}
/* The routine MD5Update updates the message-digest context to
account for the presence of each of the characters inBuf[0..inLen-1]
in the message whose digest is being computed.
*/
void MD5Update (mdContext, inBuf, inLen)
MD5_CTX *mdContext;
unsigned char *inBuf;
unsigned int inLen;
{
UINT4 in[16];
int mdi;
unsigned int i, ii;
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* update number of bits */
if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
mdContext->i[1]++;
mdContext->i[0] += ((UINT4)inLen << 3);
mdContext->i[1] += ((UINT4)inLen >> 29);
while (inLen--) {
/* add new character to buffer, increment mdi */
mdContext->in[mdi++] = *inBuf++;
/* transform if necessary */
if (mdi == 0x40) {
for (i = 0, ii = 0; i < 16; i++, ii += 4)
in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
(((UINT4)mdContext->in[ii+2]) << 16) |
(((UINT4)mdContext->in[ii+1]) << 8) |
((UINT4)mdContext->in[ii]);
Transform (mdContext->buf, in);
mdi = 0;
}
}
}
/* The routine MD5Final terminates the message-digest computation and
ends with the desired message digest in mdContext->digest[0...15].
*/
void MD5Final (mdContext)
MD5_CTX *mdContext;
{
UINT4 in[16];
int mdi;
unsigned int i, ii;
unsigned int padLen;
/* save number of bits */
in[14] = mdContext->i[0];
in[15] = mdContext->i[1];
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* pad out to 56 mod 64 */
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
MD5Update (mdContext, PADDING, padLen);
/* append length in bits and transform */
for (i = 0, ii = 0; i < 14; i++, ii += 4)
in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
(((UINT4)mdContext->in[ii+2]) << 16) |
(((UINT4)mdContext->in[ii+1]) << 8) |
((UINT4)mdContext->in[ii]);
Transform (mdContext->buf, in);
/* store buffer in digest */
for (i = 0, ii = 0; i < 4; i++, ii += 4) {
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
mdContext->digest[ii+1] =
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
mdContext->digest[ii+2] =
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
mdContext->digest[ii+3] =
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
}
}
/* Basic MD5 step. Transforms buf based on in.
*/
static void Transform (buf, in)
UINT4 *buf;
UINT4 *in;
{
UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
/* Round 2 */
#define S21 5
#define S22 9
#define S23 14
#define S24 20
GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
/* Round 3 */
#define S31 4
#define S32 11
#define S33 16
#define S34 23
HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
/* Round 4 */
#define S41 6
#define S42 10
#define S43 15
#define S44 21
II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
***********************************************************************
** End of md5.c **
******************************** (cut) ********************************
*/

58
ipppd/md5.h Normal file
View File

@ -0,0 +1,58 @@
/*
***********************************************************************
** md5.h -- header file for implementation of MD5 **
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
** Revised (for MD5): RLR 4/27/91 **
** -- G modified to have y&~z instead of y&z **
** -- FF, GG, HH modified to add in last register done **
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
** -- distinct additive constant for each step **
** -- round 4 added, working mod 7 **
***********************************************************************
*/
/*
***********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
***********************************************************************
*/
#ifndef __MD5_INCLUDE__
/* typedef a 32-bit type */
typedef unsigned int UINT4;
/* Data structure for MD5 (Message-Digest) computation */
typedef struct {
UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
UINT4 buf[4]; /* scratch buffer */
unsigned char in[64]; /* input buffer */
unsigned char digest[16]; /* actual digest after MD5Final call */
} MD5_CTX;
void MD5Init ();
void MD5Update ();
void MD5Final ();
#define __MD5_INCLUDE__
#endif /* __MD5_INCLUDE__ */

2290
ipppd/options.c Normal file

File diff suppressed because it is too large Load Diff

5
ipppd/patchlevel.h Normal file
View File

@ -0,0 +1,5 @@
#define PATCHLEVEL 8
#define VERSION "i2.2"
#define IMPLEMENTATION "anubis"
#define DATE "31. January 97"

30
ipppd/pathnames.h Normal file
View File

@ -0,0 +1,30 @@
/*
* define path names
*
* $Id: pathnames.h,v 1.1 1997/03/07 16:01:36 hipp Exp $
*/
#ifdef HAVE_PATHS_H
# include <paths.h>
#else
# define _PATH_VARRUN "/etc/ppp/"
# define _PATH_DEVNULL "/dev/null"
#endif
#define _PATH_UPAPFILE "/etc/ppp/pap-secrets"
#define _PATH_CHAPFILE "/etc/ppp/chap-secrets"
#define _PATH_SYSOPTIONS "/etc/ppp/ioptions"
#define _PATH_IPUP "/etc/ppp/ip-up"
#define _PATH_IPDOWN "/etc/ppp/ip-down"
#define _PATH_TTYOPT "/etc/ppp/ioptions."
#define _PATH_CONNERRS "/etc/ppp/connect-errors"
#define _PATH_PEERFILES "/etc/ppp/peers/"
#define _PATH_USEROPT ".ippprc"
/* Programs for processing authenticated logins */
#define _PATH_AUTHUP "/etc/ppp/auth-up"
#define _PATH_AUTHDOWN "/etc/ppp/auth-down"
# define _PATH_IPXUP "/etc/ppp/ipx-up"
# define _PATH_IPXDOWN "/etc/ppp/ipx-down"

931
ipppd/pppd.8 Normal file
View File

@ -0,0 +1,931 @@
.\" manual page [] for pppd 2.0
.\" $Id: pppd.8,v 1.1 1997/03/07 16:01:37 hipp Exp $
.\" SH section heading
.\" SS subsection heading
.\" LP paragraph
.\" IP indented paragraph
.\" TP hanging label
.TH PPPD 8
.SH NAME
pppd \- Point to Point Protocol daemon
.SH SYNOPSIS
.B pppd
[
.I tty_name
] [
.I speed
] [
.I options
]
.SH DESCRIPTION
.LP
The Point-to-Point Protocol (PPP) provides a method for transmitting
datagrams over serial point-to-point links. PPP
is composed of three parts: a method for encapsulating datagrams over
serial links, an extensible Link Control Protocol (LCP), and
a family of Network Control Protocols (NCP) for establishing
and configuring different network-layer protocols.
.LP
The encapsulation scheme is provided by driver code in the kernel.
.B pppd
provides the basic LCP, authentication support, and an
NCP for establishing and configuring the Internet Protocol (IP)
(called the IP Control Protocol, IPCP).
.SH FREQUENTLY USED OPTIONS
.TP
.I <tty_name>
Communicate over the named device. The string "/dev/"
is prepended if necessary. If no device name is given,
or if the name of the controlling terminal is given,
.I pppd
will use the controlling terminal, and will not fork to put itself in
the background.
.TP
.I <speed>
Set the baud rate to <speed> (a decimal number). On systems such as
4.4BSD and NetBSD, any speed can be specified. Other systems
(e.g. SunOS) allow only a limited set of speeds.
.TP
.B asyncmap \fI<map>
Set the async character map to <map>.
This map describes which control characters cannot be successfully
received over the serial line.
.I pppd
will ask the peer to send these characters as a 2-byte escape sequence.
The argument is a 32 bit hex number
with each bit representing a character to escape.
Bit 0 (00000001) represents the character 0x00;
bit 31 (80000000) represents the character 0x1f or ^_.
If multiple \fBasyncmap\fR options are
given, the values are ORed together.
If no \fBasyncmap\fR option is given, no async character map will be
negotiated for the receive direction; the peer should then escape
\fIall\fR control characters.
.TP
.B auth
Require the peer to authenticate itself before allowing network
packets to be sent or received.
.TP
.B connect \fI<p>
Use the executable or shell command specified by \fI<p>\fR to set up the
serial line. This script would typically use the chat(8) program to
dial the modem and start the remote ppp session.
.TP
.B crtscts
Use hardware flow control (i.e. RTS/CTS) to control the flow of data
on the serial port. If neither the \fBcrtscts\fR nor the
\fB\-crtscts\fR option is given, the hardware flow control setting for
the serial port is left unchanged.
.TP
.B defaultroute
Add a default route to the system routing tables, using the peer as
the gateway, when IPCP negotiation is successfully completed.
This entry is removed when the PPP connection is broken.
.TP
.B disconnect \fI<p>
Run the executable or shell command specified by \fI<p>\fR after
\fIpppd\fR has terminated the link. This script could, for example,
issue commands to the modem to cause it to hang up if hardware modem
control signals were not available.
.TP
.B escape \fIxx,yy,...
Specifies that certain characters should be escaped on transmission
(regardless of whether the peer requests them to be escaped with its
async control character map). The characters to be escaped are
specified as a list of hex numbers separated by commas. Note that
almost any character can be specified for the \fBescape\fR option,
unlike the \fBasyncmap\fR option which only allows control characters
to be specified. The characters which may not be escaped are those
with hex values 0x20 - 0x3f or 0x5e.
.TP
.B file \fI<f>
Read options from file <f> (the format is described below).
.TP
.B lock
Specifies that \fIpppd\fR should create a UUCP-style lock file for the
serial device to ensure exclusive access to the device.
.TP
.B mru \fI<n>
Set the MRU [Maximum Receive Unit] value to <n> for negotiation.
.I pppd
will ask the peer to send packets of no more than <n> bytes. The
minimum MRU value is 128. The default MRU value is 1500. A value of
296 is recommended for slow links (40 bytes for TCP/IP header + 256
bytes of data).
.TP
.B mtu \fI<n>
Set the MTU [Maximum Transmit Unit] value to \fI<n>\fR. Unless the
peer requests a smaller value via MRU negotiation, \fIpppd\fR will
request that the kernel networking code send data packets of no more
than \fIn\fR bytes through the PPP network interface.
.TP
.B netmask \fI<n>
Set the interface netmask to <n>, a 32 bit netmask in "decimal dot"
notation (e.g. 255.255.255.0). If this option is given, the value
specified is ORed with the default netmask. The default netmask is
chosen based on the negotiated remote IP address; it is the
appropriate network mask for the class of the remote IP address, ORed
with the netmasks for any non point-to-point network interfaces in the
system which are on the same network.
.TP
.B passive
Enables the "passive" option in the LCP. With this option,
.I pppd
will attempt to initiate a connection; if no reply is received from
the peer,
.I pppd
will then just wait passively for a valid LCP packet from the peer
(instead of exiting, as it does without this option).
.TP
.B silent
With this option,
.I 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 \fIpppd\fR).
.SH OPTIONS
.TP
.I <local_IP_address>\fB:\fI<remote_IP_address>
Set the local and/or remote interface IP addresses. Either one may be
omitted. The IP addresses can be specified with a host name or in
decimal dot notation (e.g. 150.234.56.78). The default local
address is the (first) IP address of the system (unless the
.B noipdefault
option is given). The remote address will be obtained from the peer
if not specified in any option. Thus, in simple cases, this option is
not required. If a local and/or remote IP address is specified with
this option,
.I pppd
will not accept a different value from the peer in the IPCP
negotiation, unless the
.B ipcp-accept-local
and/or
.B ipcp-accept-remote
options are given, respectively.
.TP
.B -ac
Disable Address/Control compression negotiation (use default, i.e.
address/control field compression disabled).
.TP
.B -all
Don't request or allow negotiation of any options for LCP and IPCP (use
default values).
.TP
.B -am
Disable asyncmap negotiation (use the default asyncmap, i.e. escape
all control characters).
.TP
.B -as \fI<n>
Same as
.B asyncmap \fI<n>
.TP
.B bsdcomp \fInr,nt
Request that the peer compress packets that it sends, using the
BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and
agree to compress packets sent to the peer with a maximum code size of
\fInt\fR bits. If \fInt\fR is not specified, it defaults to the value
given for \fInr\fR. Values in the range 9 to 15 may be used for
\fInr\fR and \fInt\fR; larger values give better compression but
consume more kernel memory for compression dictionaries.
Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables
compression in the corresponding direction.
.TP
.B \-bsdcomp
Disables compression; \fBpppd\fR will not request or agree to compress
packets using the BSD-Compress scheme.
.TP
.B +chap
Require the peer to authenticate itself using CHAP [Cryptographic
Handshake Authentication Protocol] authentication.
.TP
.B -chap
Don't agree to authenticate using CHAP.
.TP
.B chap-interval \fI<n>
If this option is given,
.I pppd
will rechallenge the peer every <n> seconds.
.TP
.B chap-max-challenge \fI<n>
Set the maximum number of CHAP challenge transmissions to <n> (default
10).
.TP
.B chap-restart \fI<n>
Set the CHAP restart interval (retransmission timeout for challenges)
to <n> seconds (default 3).
.TP
.B -crtscts
Disable hardware flow control (i.e. RTS/CTS) on the serial port. If
neither the \fBcrtscts\fR nor the \fB\-crtscts\fR option is given,
the hardware flow control setting for the serial port is left
unchanged.
.TP
.B -d
Increase debugging level (same as the \fBdebug\fR option).
.TP
.B debug
Increase debugging level (same as \fB\-d\fR).
If this option is given, \fIpppd\fR will log the contents of all
control packets sent or received in a readable form. The packets are
logged through syslog with facility \fIdaemon\fR and level
\fIdebug\fR. This information can be directed to a file by setting up
/etc/syslog.conf appropriately (see syslog.conf(5)).
.TP
.B \-defaultroute
Disable the \fBdefaultroute\fR option. The system administrator who
wishes to prevent users from creating default routes with \fIpppd\fR
can do so by placing this option in the /etc/ppp/options file.
.TP
.B -detach
Don't fork to become a background process (otherwise
.I pppd
will do so if a serial device other than its controlling terminal is
specified).
.TP
.B dns-addr \fI<n>
This option sets the IP address or addresses for the Domain Name
Server. It is used by Microsoft Windows clients. The primary DNS
address is specified by the first instance of the dns-addr option. The
secondary is specified by the second instance.
.TP
.B domain \fI<d>
Append the domain name <d> to the local host name for authentication
purposes. For example, if gethostname() returns the name porsche, but the
fully qualified domain name is porsche.Quotron.COM, you would use the
domain option to set the domain name to Quotron.COM.
.TP
.B -ip
Disable IP address negotiation. If this option is used, the remote IP
address must be specified with an option on the command line or in an
options file.
.TP
.B +ip-protocol
Enable the IPCP and IP protocols. This is the default condition. This
option is only needed if the default setting is -ip-protocol.
.TP
.B -ip-protocol
Disable the IPCP and IP protocols. This should only be used if you
know that you are using a client which only understands IPX and you
don't want to confuse the client with the IPCP protocol.
.TP
.B +ipx-protocol
Enable the IPXCP and IPX protocols. This is the default condition if
your kernel supports IPX. This option is only needed if the default
setting is -ipx-protocol. If your kernel does not support IPX then this
option will have no effect.
.TP
.B -ipx-protocol
Disable the IPXCP and IPX protocols. This should only be used if you
know that you are using a client which only understands IP and you
don't want to confuse the client with the IPXCP protocol.
.TP
.B ipcp-accept-local
With this option,
.I pppd
will accept the peer's idea of our local IP address, even if the
local IP address was specified in an option.
.TP
.B ipcp-accept-remote
With this option,
.I pppd
will accept the peer's idea of its (remote) IP address, even if the
remote IP address was specified in an option.
.TP
.B ipcp-max-configure \fI<n>
Set the maximum number of IPCP configure-request transmissions to <n>
(default 10).
.TP
.B ipcp-max-failure \fI<n>
Set the maximum number of IPCP configure-NAKs returned before starting
to send configure-Rejects instead to <n> (default 10).
.TP
.B ipcp-max-terminate \fI<n>
Set the maximum number of IPCP terminate-request transmissions to <n>
(default 3).
.TP
.B ipcp-restart \fI<n>
Set the IPCP restart interval (retransmission timeout) to <n> seconds
(default 3).
.TP
.B ipparam \fIstring
Provides an extra parameter to the ip-up and ip-down scripts. If this
option is given, the \fIstring\fR supplied is given as the 6th
parameter to those scripts.
.TP
.B ipx-network \fI<n>
Set the IPX network number in the IPXCP configure request frame to
<n>. There is no valid default. If this option is not specified then
the network number is obtained from the peer. If the peer does not
have the network number, the IPX protocol will not be started. This is
a hexadecimal number and is entered without any leading sequence such
as 0x. It is related to the \fIipxcp-accept-network\fR option.
.TP
.B ipx-node \fI<n>:<m>
Set the IPX node numbers. The two node numbers are separated from each
other with a colon character. The first number <n> is the local node
number. The second number <m> is the peer's node number. Each node number
is a hexadecimal number, to the maximum of ten significant digits. The
node numbers on the ipx-network must be unique. There is no valid
default. If this option is not specified then the node number is
obtained from the peer. This option is a related to the
\fIipxcp-accept-local\fR and \fIipxcp-accept-remote\fR options.
.TP
.B ipx-router-name \fI<string>
Set the name of the router. This is a string and is sent to the peer
as information data.
.TP
.B ipx-routing \fI<n>
Set the routing protocol to be received by this option. More than one
instance of \fIipx-routing\fR may be specified. The '\fInone\fR'
option (0) may be specified as the only instance of ipx-routing. The
values may be \fI0\fR for \fINONE\fR, \fI2\fR for \fIRIP/SAP\fR, and
\fI4\fR for \fINLSP\fR.
.TP
.B ipxcp-accept-local
Accept the peer's NAK for the node number specified in the ipx-node
option. If a node number was specified, and non-zero, the default is
to insist that the value be used. If you include this option then you
will permit the peer to override the entry of the node number.
.TP
.B ipxcp-accept-network
Accept the peer's NAK for the network number specified in the
ipx-network option. If a network number was specified, and non-zero, the
default is to insist that the value be used. If you include this
option then you will permit the peer to override the entry of the node
number.
.TP
.B ipxcp-accept-remote
Use the peer's network number specified in the configure request
frame. If a node number was specified for the peer and this option was
not specified, the peer will be forced to use the value which you have
specified.
.TP
.B ipxcp-max-configure \fI<n>
Set the maximum number of IPXCP configure request frames which the
system will send to <n>. The default is 10.
.TP
.B ipxcp-max-failure \fI<n>
Set the maximum number of IPXCP NAK frames which the local system will
send before it rejects the options. The default value is 3.
.TP
.B ipxcp-max-terminate \fI<n>
Set the maximum nuber of IPXCP terminate request frames before the
local system considers that the peer is not listening to them. The
default value is 3.
.TP
.B kdebug \fIn
Enable debugging code in the kernel-level PPP driver. The argument
\fIn\fR is a number which is the sum of the following values: 1 to
enable general debug messages, 2 to request that the contents of
received packets be printed, and 4 to request that the contents of
transmitted packets be printed.
.TP
.B lcp-echo-failure \fI<n>
If this option is given, \fIpppd\fR will presume the peer to be dead
if \fIn\fR LCP echo-requests are sent without receiving a valid LCP
echo-reply. If this happens, \fIpppd\fR will terminate the
connection. Use of this option requires a non-zero value for the
\fIlcp-echo-interval\fR parameter. This option can be used to enable
\fIpppd\fR to terminate after the physical connection has been broken
(e.g., the modem has hung up) in situations where no hardware modem
control lines are available.
.TP
.B lcp-echo-interval \fI<n>
If this option is given, \fIpppd\fR will send an LCP echo-request
frame to the peer every \fIn\fR seconds. Under Linux, the
echo-request is sent when no packets have been received from the peer
for \fIn\fR seconds. Normally the peer should respond to the
echo-request by sending an echo-reply. This option can be used with
the \fIlcp-echo-failure\fR option to detect that the peer is no longer
connected.
.TP
.B lcp-max-configure \fI<n>
Set the maximum number of LCP configure-request transmissions to <n>
(default 10).
.TP
.B lcp-max-failure \fI<n>
Set the maximum number of LCP configure-NAKs returned before starting
to send configure-Rejects instead to <n> (default 10).
.TP
.B lcp-max-terminate \fI<n>
Set the maximum number of LCP terminate-request transmissions to <n>
(default 3).
.TP
.B lcp-restart \fI<n>
Set the LCP restart interval (retransmission timeout) to <n> seconds
(default 3).
.TP
.B local
Don't use the modem control lines. With this option,
.B pppd
will ignore the state of the CD (Carrier Detect) signal from the modem and
will not change the state of the DTR (Data Terminal Ready) signal.
.TP
.B login
Use the system password database for authenticating the peer using
PAP, and record the user in the system wtmp file.
.TP
.B modem
Use the modem control lines. This option is the default. With this
option,
.B pppd
will wait for the CD (Carrier Detect) signal from the modem to be asserted
when opening the serial device
(unless a connect script is specified), and it will drop the DTR (Data
Terminal Ready) signal briefly when the connection is terminated and before
executing the connect script.
On Ultrix, this option implies hardware
flow control, as for the \fBcrtscts\fR option.
.TP
.B -mn
Disable magic number negotiation. With this option,
.I pppd
cannot detect a looped-back line.
.TP
.B -mru
Disable MRU [Maximum Receive Unit] negotiation. With this option,
\fIpppd\fR will use the default MRU value of 1500 bytes.
.TP
.B name \fI<n>
Set the name of the local system for authentication purposes to <n>.
.TP
.B noipdefault
Disables the default behaviour when no local IP address is specified,
which is to determine (if possible) the local IP address from the
hostname. With this option, the peer will have to supply the local IP
address during IPCP negotiation (unless it specified explicitly on the
command line or in an options file).
.TP
.B -p
Same as the
.B passive
option.
.TP
.B +pap
Require the peer to authenticate itself using PAP.
.TP
.B -pap
Don't agree to authenticate using PAP.
.TP
.B papcrypt
Indicates that all secrets in the /etc/ppp/pap-secrets file which
are used for checking the identity of the peer are encrypted, and thus
pppd should not accept a password which (before encryption) is
identical to the secret from the /etc/ppp/pap-secrets file.
.TP
.B pap-max-authreq \fI<n>
Set the maximum number of PAP authenticate-request transmissions to
<n> (default 10).
.TP
.B pap-restart \fI<n>
Set the PAP restart interval (retransmission timeout) to <n> seconds
(default 3).
.TP
.B pap-timeout \fI<n>
Set the maximum time that
.I pppd
will wait for the peer to authenticate itself with PAP to
<n> seconds (0 means no limit).
.TP
.B -pc
Disable protocol field compression negotiation (use default, i.e.
protocol field compression disabled).
.TP
.B persist
Do not exit after a connection is terminated; instead try to reopen
the connection.
.TP
.B pred1comp
Attempt to request that the peer send the local system frames which
have been compressed by the Predictor-1 compression. The compression
protocols must be loaded or this option will be ignored.
.TP
.B -pred1comp
Do not accept Predictor-1 comprssion, even if the peer wants to send
this type of compression and support has been defined in the kernel.
.TP
.B proxyarp
Add an entry to this system's ARP [Address Resolution Protocol] table
with the IP address of the peer and the Ethernet address of this
system.
.TP
.B \-proxyarp
Disable the \fBproxyarp\fR option. The system administrator who
wishes to prevent users from creating proxy ARP entries with
\fIpppd\fR can do so by placing this option in the /etc/ppp/options
file.
.TP
.B remotename \fI<n>
Set the assumed name of the remote system for authentication purposes
to <n>.
.TP
.B +ua \fI<p>
Agree to authenticate using PAP [Password Authentication Protocol] if
requested by the peer, and
use the data in file <p> for the user and password to send to the
peer. The file contains the remote user name, followed by a newline,
followed by the remote password, followed by a newline. This option
is obsolescent.
.TP
.B usehostname
Enforce the use of the hostname as the name of the local system for
authentication purposes (overrides the
.B name
option).
.TP
.B user \fI<u>
Set the user name to use for authenticating this machine with the peer
using PAP to <u>.
.TP
.B -vj
Disable negotiation of Van Jacobson style TCP/IP header compression (use
default, i.e. no compression).
.TP
.B -vjccomp
Disable the connection-ID compression option in Van Jacobson style
TCP/IP header compression. With this option, \fIpppd\fR will not omit
the connection-ID byte from Van Jacobson compressed TCP/IP headers,
nor ask the peer to do so.
.TP
.B vj-max-slots \fIn
Sets the number of connection slots to be used by the Van Jacobson
TCP/IP header compression and decompression code to \fIn\fR, which
must be between 2 and 16 (inclusive).
.TP
.B xonxoff
Use software flow control (i.e. XON/XOFF) to control the flow of data on
the serial port. This option is only implemented on Linux systems
at present.
.SH OPTIONS FILES
Options can be taken from files as well as the command line.
.I pppd
reads options from the files /etc/ppp/options and ~/.ppprc before
looking at the command line. An options file is parsed into a series
of words, delimited by whitespace. Whitespace can be included in a
word by enclosing the word in quotes ("). A backslash (\\) quotes the
following character. A hash (#) starts a comment, which continues
until the end of the line.
.SH AUTHENTICATION
.I pppd
provides system administrators with sufficient access control that PPP
access to a server machine can be provided to legitimate users without
fear of compromising the security of the server or the network it's
on. In part this is provided by the /etc/ppp/options file, where the
administrator can place options to require authentication whenever
.I pppd
is run, and in part by the PAP and CHAP secrets files, where the
administrator can restrict the set of IP addresses which individual
users may use.
.LP
The default behaviour of
.I pppd
is to agree to authenticate if requested, and to not
require authentication from the peer. However,
.I pppd
will not agree to
authenticate itself with a particular protocol if it has no secrets
which could be used to do so.
.LP
Authentication is based on secrets, which are selected from secrets
files (/etc/ppp/pap-secrets for PAP, /etc/ppp/chap-secrets for CHAP).
Both secrets files have the same format, and both can store secrets
for several combinations of server (authenticating peer) and client
(peer being authenticated). Note that
.I pppd
can be both a server
and client, and that different protocols can be used in the two
directions if desired.
.LP
A secrets file is parsed into words as for a options file. A secret
is specified by a line containing at least 3 words, in the order
client name, server name, secret. Any following words on the same line are
taken to be a list of acceptable IP addresses for that client. If
there are only 3 words on the line, it is assumed that any IP address
is OK; to disallow all IP addresses, use "-". If the secret starts
with an `@', what follows is assumed to be the name of a file from
which to read the secret. A "*" as the client or server name matches
any name. When selecting a secret, \fIpppd\fR takes the best match, i.e.
the match with the fewest wildcards.
.LP
Thus a secrets file contains both secrets for use in authenticating
other hosts, plus secrets which we use for authenticating ourselves to
others. Which secret to use is chosen based on the names of the host
(the `local name') and its peer (the `remote name'). The local name
is set as follows:
.TP 3
if the \fBusehostname\fR option is given,
then the local name is the hostname of this machine
(with the domain appended, if given)
.TP 3
else if the \fBname\fR option is given,
then use the argument of the first \fBname\fR option seen
.TP 3
else if the local IP address is specified with a hostname,
then use that name
.TP 3
else use the hostname of this machine (with the domain appended, if given)
.LP
When authenticating ourselves using PAP, there is also a `username'
which is the local name by default, but can be set with the \fBuser\fR
option or the \fB+ua\fR option.
.LP
The remote name is set as follows:
.TP 3
if the \fBremotename\fR option is given,
then use the argument of the last \fBremotename\fR option seen
.TP 3
else if the remote IP address is specified with a hostname,
then use that host name
.TP 3
else the remote name is the null string "".
.LP
Secrets are selected from the PAP secrets file as follows:
.TP 2
*
For authenticating the peer, look for a secret with client ==
username specified in the PAP authenticate-request, and server ==
local name.
.TP 2
*
For authenticating ourselves to the peer, look for a secret with
client == our username, server == remote name.
.LP
When authenticating the peer with PAP, a secret of "" matches any
password supplied by the peer. If the password doesn't match the
secret, the password is encrypted using crypt() and checked against
the secret again; thus secrets for authenticating the peer can be
stored in encrypted form. If the \fBpapcrypt\fR option is given, the
first (unencrypted) comparison is omitted, for better security.
.LP
If the \fBlogin\fR option was specified, the
username and password are also checked against the system password
database. Thus, the system administrator can set up the pap-secrets
file to allow PPP access only to certain users, and to restrict the
set of IP addresses that each user can use. Typically, when using the
\fBlogin\fR option, the secret in /etc/ppp/pap-secrets would be "", to
avoid the need to have the same secret in two places.
.LP
Secrets are selected from the CHAP secrets file as follows:
.TP 2
*
For authenticating the peer, look for a secret with client == name
specified in the CHAP-Response message, and server == local name.
.TP 2
*
For authenticating ourselves to the peer, look for a secret with
client == local name, and server == name specified in the
CHAP-Challenge message.
.LP
Authentication must be satisfactorily completed before IPCP (or any
other Network Control Protocol) can be started. If authentication
fails, \fIpppd\fR will terminated the link (by closing LCP). If IPCP
negotiates an unacceptable IP address for the remote host, IPCP will
be closed. IP packets can only be sent or received when IPCP is open.
.LP
In some cases it is desirable to allow some hosts which can't
authenticate themselves to connect and use one of a restricted set of
IP addresses, even when the local host generally requires
authentication. If the peer refuses to authenticate itself when
requested, \fIpppd\fR takes that as equivalent to authenticating with
PAP using the empty string for the username and password. Thus, by
adding a line to the pap-secrets file which specifies the empty string
for the client and password, it is possible to allow restricted access
to hosts which refuse to authenticate themselves.
.SH ROUTING
.LP
When IPCP negotiation is completed successfully,
.I pppd
will inform the kernel of the local and remote IP addresses for the
ppp interface. This is sufficient to create a
host route to the remote end of the link, which will enable the peers
to exchange IP packets. Communication with other machines generally
requires further modification to routing tables and/or ARP (Address
Resolution Protocol) tables. In some cases this will be done
automatically through the actions of the \fIrouted\fR or \fIgated\fR
daemons, but in most cases some further intervention is required.
.LP
Sometimes it is desirable
to add a default route through the remote host, as in the case of a
machine whose only connection to the Internet is through the ppp
interface. The \fBdefaultroute\fR option causes \fIpppd\fR to create such a
default route when IPCP comes up, and delete it when the link is
terminated.
.LP
In some cases it is desirable to use proxy ARP, for example on a
server machine connected to a LAN, in order to allow other hosts to
communicate with the remote host. The \fBproxyarp\fR option causes \fIpppd\fR
to look for a network interface on the same subnet as the remote host
(an interface supporting broadcast and ARP, which is up and not a
point-to-point or loopback interface). If found, \fIpppd\fR creates a
permanent, published ARP entry with the IP address of the remote host
and the hardware address of the network interface found.
.SH EXAMPLES
.LP
In the simplest case, you can connect the serial ports of two machines
and issue a command like
.IP
pppd /dev/ttya 9600 passive
.LP
to each machine, assuming there is no \fIgetty\fR running on the
serial ports. If one machine has a \fIgetty\fR running, you can use
\fIkermit\fR or \fItip\fR on the other machine to log in to the first
machine and issue a command like
.IP
pppd passive
.LP
Then exit from the communications program (making sure the connection
isn't dropped), and issue a command like
.IP
pppd /dev/ttya 9600
.LP
The process of logging in to the other machine and starting \fIpppd\fR
can be automated by using the \fBconnect\fR option to run \fIchat\fR,
for example:
.IP
pppd /dev/ttya 38400 connect 'chat "" "" "login:" "username"
"Password:" "password" "% " "exec pppd passive"'
.LP
(Note however that running chat like this will leave the password
visible in the parameter list of pppd and chat.)
.LP
If your serial connection is any more complicated than a piece of
wire, you may need to arrange for some control characters to be
escaped. In particular, it is often useful to escape XON (^Q) and
XOFF (^S), using \fBasyncmap a0000\fR. If the path includes a telnet,
you probably should escape ^] as well (\fBasyncmap 200a0000\fR).
If the path includes an rlogin, you will need to use the \fBescape
ff\fR option on the end which is running the rlogin client, since many
rlogin implementations are not
transparent; they will remove the sequence [0xff, 0xff, 0x73, 0x73,
followed by any 8 bytes] from the stream.
.SH DIAGNOSTICS
.LP
Messages are sent to the syslog daemon using facility LOG_DAEMON.
(This can be overriden by recompiling \fIpppd\fR with the macro
LOG_PPP defined as the desired facility.) In order to see the error
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 \fBdebug\fR option causes the contents of all control packets sent
or received to be logged, that is, all LCP, PAP, CHAP or IPCP packets.
This can be useful if the PPP negotiation does not succeed.
If debugging is enabled at compile time, the \fBdebug\fR option also
causes other debugging messages to be logged.
.LP
Debugging can also be enabled or disabled by sending a
SIGUSR1 to the
.I pppd
process. This signal acts as a toggle.
.SH FILES
.TP
.B /var/run/ppp\fIn\fB.pid \fR(BSD or Linux), \fB/etc/ppp/ppp\fIn\fB.pid \fR(others)
Process-ID for \fIpppd\fR process on ppp interface unit \fIn\fR.
.TP
.B /etc/ppp/ip-up
A program or script which is executed when the link is available for
sending and receiving IP packets (that is, IPCP has come up). It is
executed with the parameters
.IP
\fIinterface-name tty-device speed local-IP-address
remote-IP-address\fR
.IP
and with its standard input,
output and error streams redirected to \fB/dev/null\fR.
.IP
This program or script is executed with the same real and effective
user-ID as \fIpppd\fR, that is, at least the effective user-ID and
possibly the real user-ID will be \fBroot\fR. This is so that it can
be used to manipulate routes, run privileged daemons (e.g.
\fBsendmail\fR), etc. Be careful that the contents of the
/etc/ppp/ip-up and /etc/ppp/ip-down scripts do not compromise your
system's security.
.TP
.B /etc/ppp/ip-down
A program or script which is executed when the link is no longer
available for sending and receiving IP packets. This script can be
used for undoing the effects of the /etc/ppp/ip-up script. It is
invoked with the same parameters as the ip-up script, and the same
security considerations apply, since it is executed with the same
effective and real user-IDs as \fIpppd\fR.
.TP
.B /etc/ppp/ipx-up
A program or script which is executed when the link is available for
sending and receiving IPX packets (that is, IPXCP has come up). It is
executed with the parameters
.IP
\fIinterface-name tty-device speed network-number local-IPX-node-address
remote-IPX-node-address local-IPX-routing-protocol remote-IPX-routing-protocol
local-IPX-router-name remote-IPX-router-name ipparam pppd-pid\fR
.IP
and with its standard input,
output and error streams redirected to \fB/dev/null\fR.
.br
.IP
The local-IPX-routing-protocol and remote-IPX-routing-protocol field
may be one of the following:
.IP
NONE to indicate that there is no routing protocol
.br
RIP to indicate that RIP/SAP should be used
.br
NLSP to indicate that Novell NLSP should be used
.br
RIP NLSP to indicate that both RIP/SAP and NLSP should be used
.br
.IP
This program or script is executed with the same real and effective
user-ID as \fIpppd\fR, that is, at least the effective user-ID and
possibly the real user-ID will be \fBroot\fR. This is so that it can
be used to manipulate routes, run privileged daemons (e.g.
\fBripd\fR), etc. Be careful that the contents of the
/etc/ppp/ipx-up and /etc/ppp/ipx-down scripts do not compromise your
system's security.
.TP
.B /etc/ppp/ipx-down
A program or script which is executed when the link is no longer
available for sending and receiving IPX packets. This script can be
used for undoing the effects of the /etc/ppp/ipx-up script. It is
invoked with the same parameters as the ipx-up script, and the same
security considerations apply, since it is executed with the same
effective and real user-IDs as \fIpppd\fR.
.TP
.B /etc/ppp/pap-secrets
Usernames, passwords and IP addresses for PAP authentication.
.TP
.B /etc/ppp/chap-secrets
Names, secrets and IP addresses for CHAP authentication.
.TP
.B /etc/ppp/options
System default options for
.I pppd,
read before user default options or command-line options.
.TP
.B ~/.ppprc
User default options, read before command-line options.
.TP
.B /etc/ppp/options.\fIttyname
System default options for the serial port being used, read after
command-line options.
.SH SEE ALSO
.TP
.B RFC1144
Jacobson, V.
.I Compressing TCP/IP headers for low-speed serial links.
1990 February.
.TP
.B RFC1321
Rivest, R.
.I The MD5 Message-Digest Algorithm.
1992 April.
.TP
.B RFC1332
McGregor, G.
.I PPP Internet Protocol Control Protocol (IPCP).
1992 May.
.TP
.B RFC1334
Lloyd, B.; Simpson, W.A.
.I PPP authentication protocols.
1992 October.
.TP
.B RFC1548
Simpson, W.A.
.I The Point\-to\-Point Protocol (PPP).
1993 December.
.TP
.B RFC1549
Simpson, W.A.
.I PPP in HDLC Framing.
1993 December
.SH NOTES
The following signals have the specified effect when sent to the
.I pppd
process.
.TP
.B SIGINT, SIGTERM
These signals cause \fBpppd\fR to terminate the link (by closing LCP),
restore the serial device settings, and exit.
.TP
.B SIGHUP
This signal causes \fBpppd\fR to terminate the link, restore the
serial device settings, and close the serial device. If the
\fBpersist\fR option has been specified, \fBpppd\fR will try to reopen
the serial device and start another connection. Otherwise \fBpppd\fR
will exit.
.TP
.B SIGUSR2
This signal causes
.B pppd
to renegotiate compression. This can be useful to re-enable
compression after it has been disabled as a result of a fatal
decompression error. With the BSD Compress scheme, fatal
decompression errors generally indicate a bug in one or other
implementation.
.SH AUTHORS
Drew Perkins,
Brad Clements,
Karl Fox,
Greg Christy,
Brad Parker,
Paul Mackerras (paulus@cs.anu.edu.au).

439
ipppd/pppd.h Normal file
View File

@ -0,0 +1,439 @@
/*
* pppd.h - PPP daemon global declarations.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id: pppd.h,v 1.1 1997/03/07 16:01:39 hipp Exp $
*/
/*
* TODO:
*/
#define ISDN4LINUX_PATCH
#ifndef __PPPD_H__
#define __PPPD_H__
#include <stdarg.h>
#include <sys/param.h> /* for MAXPATHLEN and BSD4_4, if defined */
#include <sys/types.h> /* for u_int32_t, if defined */
#include <sys/bitypes.h>
#include <linux/ppp_defs.h>
#include <linux/isdn_ppp.h>
#include <stdio.h>
#include <net/if.h>
#define NUM_PPP 16 /* 16 PPP interface supported (per process) */
struct wordlist {
struct wordlist *next;
char word[1];
};
struct link_struct {
struct link_struct *bundle_next;
int fd; /* link file descriptor */
int peer_mru; /* link: peer_mru */
int logged_in;
int auth_pending;
struct wordlist *addresses;
int unit; /* link unit */
int lcp_unit;
int ipcp_unit;
int ccp_unit;
int chap_unit;
int upap_unit;
int cbcp_unit;
int ipxcp_unit;
int phase;
int auth_up_script;
int kill_link;
int open_ccp_flag;
int ifunit;
int openfails;
char ifname[IFNAMSIZ];
char devnam[MAXPATHLEN];
char peer_authname[64];
int initfdflags;
int hungup;
struct pppcallinfo pci;
};
extern struct link_struct lns[NUM_PPP];
/*
* Limits.
*/
#define MAXWORDLEN 1024 /* max length of word in file (incl null) */
#define MAXARGS 1 /* max # args to a command */
#define MAXNAMELEN 256 /* max length of hostname or name for auth */
#define MAXSECRETLEN 256 /* max length of password or secret */
/*
* Global variables.
*/
extern char hostname[]; /* Our hostname */
extern u_char outpacket_buf[]; /* Buffer for outgoing packets */
extern int baud_rate; /* Current link speed in bits/sec */
extern char *progname; /* Name of this program */
/*
* Variables set by command-line options.
*/
extern int usefirstip,useifip,useifmtu;
extern int numdev; /* number of handled devices */
extern int debug; /* Debug flag */
extern int kdebugflag; /* Tell kernel to print debug messages */
extern int default_device; /* Using /dev/tty or equivalent */
extern int crtscts; /* Use hardware flow control */
extern int modem; /* Use modem control lines */
extern int inspeed; /* Input/Output speed requested */
extern u_int32_t netmask; /* IP netmask to set on interface */
extern int lockflag; /* Create lock file to lock the serial dev */
extern int nodetach; /* Don't detach from controlling tty */
extern char *connector; /* Script to establish physical link */
extern char *disconnector; /* Script to disestablish physical link */
extern char user[]; /* Username for PAP */
extern char passwd[]; /* Password for PAP */
extern int auth_required; /* Peer is required to authenticate */
extern int proxyarp; /* Set up proxy ARP entry for peer */
extern int persist; /* Reopen link after it goes down */
extern int uselogin; /* Use /etc/passwd for checking PAP */
extern int lcp_echo_interval; /* Interval between LCP echo-requests */
extern int lcp_echo_fails; /* Tolerance to unanswered echo-requests */
extern char our_name[]; /* Our name for authentication purposes */
extern char remote_name[]; /* Peer's name for authentication */
extern int usehostname; /* Use hostname for our_name */
extern int disable_defaultip; /* Don't use hostname for default IP adrs */
extern char *ipparam; /* Extra parameter for ip up/down scripts */
extern int cryptpap; /* Others' PAP passwords are encrypted */
#ifdef __linux__
extern int hostroute; /* Add a route to the host at the other end? */
#endif
/*
* Values for phase.
*/
#define PHASE_WAIT -1
#define PHASE_DEAD 0
#define PHASE_ESTABLISH 1
#define PHASE_AUTHENTICATE 2
#define PHASE_CALLBACK 3
#define PHASE_NETWORK 4
#define PHASE_TERMINATE 5
/*
* The following struct gives the addresses of procedures to call
* for a particular protocol.
*/
struct protent {
u_short protocol; /* PPP protocol number */
/* Initialization procedure */
void (*init) __P((int unit));
/* Process a received packet */
void (*input) __P((int unit, u_char *pkt, int len));
/* Process a received protocol-reject */
void (*protrej) __P((int unit));
/* Lower layer has come up */
void (*lowerup) __P((int unit));
/* Lower layer has gone down */
void (*lowerdown) __P((int unit));
/* Open the protocol */
void (*open) __P((int unit));
/* Close the protocol */
void (*close) __P((int unit, char *reason));
/* Print a packet in readable form */
int (*printpkt) __P((u_char *pkt, int len,
void (*printer) __P((void *, char *, ...)),
void *arg));
/* Process a received data packet */
void (*datainput) __P((int unit, u_char *pkt, int len));
int enabled_flag; /* 0 iff protocol is disabled */
char *name; /* Text name of protocol */
/* Check requested options, assign defaults */
void (*check_options) __P((void));
/* Configure interface for demand-dial */
int (*demand_conf) __P((int unit));
/* Say whether to bring up link for this pkt */
int (*active_pkt) __P((u_char *pkt, int len));
};
/* Table of pointers to supported protocols */
extern struct protent *protocols[];
/*
* Prototypes.
*/
void quit __P((void)); /* Cleanup and exit */
void timeout __P((void (*)(), caddr_t, int));
/* Look-alike of kernel's timeout() */
void untimeout __P((void (*)(), caddr_t));
/* Look-alike of kernel's untimeout() */
void output __P((int, u_char *, int));
/* Output a PPP packet */
void demuxprotrej __P((int,u_short));
/* Demultiplex a Protocol-Reject */
int check_passwd __P((int, char *, int, char *, int, char **, int *));
/* Check peer-supplied username/password */
int get_secret __P((int, char *, char *, char *, int *, int));
/* get "secret" for chap */
u_int32_t GetMask __P((u_int32_t)); /* get netmask for address */
void die __P((int));
void check_access __P((FILE *, char *));
int ccp_getunit(int);
int ipcp_getunit(int);
int lcp_getunit(int);
void ccp_freeunit(int);
void ipcp_freeunit(int);
void lcp_freeunit(int);
char *ip_ntoa(u_int32_t);
int bad_ip_adrs(u_int32_t);
int getword(FILE *,char *,int *,char *);
void print_string(char *p,int len,void (*printer)(void *,char *,...),void *arg);
int auth_ip_addr(int unit,u_int32_t addr);
void auth_peer_fail(int,int);
void auth_withpeer_fail(int unit,int protocol);
void auth_peer_success(int unit,int protocol);
void auth_withpeer_success(int unit,int protocol);
void link_required(int);
void link_terminated(int);
void link_down(int);
void link_established(int unit);
int device_script(char *program,int in,int out);
void check_auth_options(void);
void setipdefault(void);
int options_from_file(char *filename,int must_exist,int check_prot,int slot);
int options_for_tty(void);
int options_from_user(void);
int parse_args(int argc,char **argv);
int run_program(char *prog,char **args,int must_exist,int tu);
void establish_ppp __P((int));
void calltimeout __P((void));
struct timeval *timeleft __P((struct timeval *));
void reap_kids __P((void));
void cleanup __P((int, caddr_t,int));
void close_fd __P((int));
void die __P((int));
void novm __P((char *));
void log_packet __P((u_char *, int, char *,int));
void format_packet __P((u_char *,int,void (*) (void *, char *, ...), void *,int));
void pr_log __P((void *, char *, ...));
void sys_init(void);
void note_debug_level (void);
void output (int unit, unsigned char *p, int len);
void wait_input (struct timeval *timo);
int read_packet (unsigned char *buf,int tu);
void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp);
void ppp_set_xaccm (int unit, ext_accm accm);
void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp);
int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit);
void ccp_flags_set (int unit, int isopen, int isup);
int ccp_fatal_error (int unit);
int sifvjcomp (int unit, int vjcomp, int cidcomp, int maxcid);
int sifup (int u);
int sifdown (int u);
int sifbundle(int,int);
int sifaddr (int unit, int our_adr, int his_adr, int net_mask);
int cifaddr (int unit, int our_adr, int his_adr);
int sifdefaultroute (int unit, int gateway);
int cifdefaultroute (int unit, int gateway);
int sifproxyarp (int unit, u_int32_t his_adr);
int cifproxyarp (int unit, u_int32_t his_adr);
int sipxfaddr (int unit, u_int32_t network, unsigned char * node );
int cipxfaddr (int linkunit);
int ppp_available(void);
int logwtmp (int unit,char *line, char *name, char *host);
int lock (char *dev);
void unlock(void);
void setifip(int);
extern void enable_mp(int,int);
void remove_sys_options(void);
u_int32_t magic(void);
int fmtmsg __P((char *, int, char *, ...)); /* sprintf++ */
int vfmtmsg __P((char *, int, char *, va_list)); /* vsprintf++ */
void option_error __P((char *fmt, ...));
void usage __P((void)); /* Print a usage message */
/*
* This structure is used to store information about certain
* options, such as where the option value came from (/etc/ppp/options,
* command line, etc.) and whether it came from a privileged source.
*/
struct option_info {
int priv; /* was value set by sysadmin? */
char *source; /* where option came from */
};
extern struct option_info auth_req_info;
extern struct option_info connector_info;
extern struct option_info disconnector_info;
extern struct option_info welcomer_info;
extern struct option_info devnam_info;
/*
* Inline versions of get/put char/short/long.
* Pointer is advanced; we assume that both arguments
* are lvalues and will already be in registers.
* cp MUST be u_char *.
*/
#define GETCHAR(c, cp) { \
(c) = *(cp)++; \
}
#define PUTCHAR(c, cp) { \
*(cp)++ = (u_char) (c); \
}
#define GETSHORT(s, cp) { \
(s) = *(cp)++ << 8; \
(s) |= *(cp)++; \
}
#define PUTSHORT(s, cp) { \
*(cp)++ = (u_char) ((s) >> 8); \
*(cp)++ = (u_char) (s); \
}
#define GETLONG(l, cp) { \
(l) = *(cp)++ << 8; \
(l) |= *(cp)++; (l) <<= 8; \
(l) |= *(cp)++; (l) <<= 8; \
(l) |= *(cp)++; \
}
#define PUTLONG(l, cp) { \
*(cp)++ = (u_char) ((l) >> 24); \
*(cp)++ = (u_char) ((l) >> 16); \
*(cp)++ = (u_char) ((l) >> 8); \
*(cp)++ = (u_char) (l); \
}
#define INCPTR(n, cp) ((cp) += (n))
#define DECPTR(n, cp) ((cp) -= (n))
#undef FALSE
#define FALSE 0
#undef TRUE
#define TRUE 1
/*
* System dependent definitions for user-level 4.3BSD UNIX implementation.
*/
#define DEMUXPROTREJ(u, p) demuxprotrej(u, p)
#define TIMEOUT(r, f, t) timeout((r), (f), (t))
#define UNTIMEOUT(r, f) untimeout((r), (f))
#define BCOPY(s, d, l) memcpy(d, s, l)
#define BZERO(s, n) memset(s, 0, n)
#define EXIT(u) quit()
#define PRINTMSG(m, l) { m[l] = '\0'; syslog(LOG_INFO, "Remote message: %s", m); }
/*
* MAKEHEADER - Add Header fields to a packet.
*/
#define MAKEHEADER(p, t) { \
PUTCHAR(PPP_ALLSTATIONS, p); \
PUTCHAR(PPP_UI, p); \
PUTSHORT(t, p); }
#ifdef DEBUGALL
#define DEBUGMAIN 1
#define DEBUGFSM 1
#define DEBUGLCP 1
#define DEBUGIPCP 1
#define DEBUGIPXCP 1
#define DEBUGUPAP 1
#define DEBUGCHAP 1
#endif
#ifndef LOG_PPP /* we use LOG_LOCAL2 for syslog by default */
#if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUG) \
|| defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \
|| defined(DEBUGCHAP) || defined(DEBUGIPXCP)
#define LOG_PPP LOG_LOCAL2
#else
#define LOG_PPP LOG_DAEMON
#endif
#endif /* LOG_PPP */
#ifdef DEBUGMAIN
#define MAINDEBUG(x) if (debug) syslog x
#else
#define MAINDEBUG(x)
#endif
#ifdef DEBUGFSM
#define FSMDEBUG(x) if (debug) syslog x
#else
#define FSMDEBUG(x)
#endif
#ifdef DEBUGLCP
#define LCPDEBUG(x) if (debug) syslog x
#else
#define LCPDEBUG(x)
#endif
#ifdef DEBUGIPCP
#define IPCPDEBUG(x) if (debug) syslog x
#else
#define IPCPDEBUG(x)
#endif
#ifdef DEBUGIPXCP
#define IPXCPDEBUG(x) if (debug) syslog x
#else
#define IPXCPDEBUG(x)
#endif
#ifdef DEBUGUPAP
#define UPAPDEBUG(x) if (debug) syslog x
#else
#define UPAPDEBUG(x)
#endif
#ifdef DEBUGCHAP
#define CHAPDEBUG(x) if (debug) syslog x
#else
#define CHAPDEBUG(x)
#endif
#ifndef SIGTYPE
#if defined(sun) || defined(SYSV) || defined(POSIX_SOURCE)
#define SIGTYPE void
#else
#define SIGTYPE int
#endif /* defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) */
#endif /* SIGTYPE */
#ifndef MIN
#define MIN(a, b) ((a) < (b)? (a): (b))
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b)? (a): (b))
#endif
#endif /* __PPP_H__ */

97
ipppd/protos.h Normal file
View File

@ -0,0 +1,97 @@
struct protos {
unsigned int val;
char *name;
};
struct protos protonames[] = {
{ 0x0001,"Padding Protocol" },
{ 0x0021,"Internet Protocol" },
{ 0x0023,"OSI Network Layer" },
{ 0x0025,"Xerox NS IDP" },
{ 0x0027,"DECnet Phase IV" },
{ 0x0029,"Appletalk" },
{ 0x002b,"Novell IPX" },
{ 0x002d,"Van Jacobson Compressed TCP/IP" },
{ 0x002f,"Van Jacobson Uncompressed TCP/IP" },
{ 0x0031,"Bridging PDU" },
{ 0x0033,"Stream Protocol (ST-II)" },
{ 0x0035,"Banyan Vines" },
{ 0x0037,"reserved (until 1993)" },
{ 0x0039,"AppleTalk EDDP" },
{ 0x003b,"AppleTalk SmartBuffered" },
{ 0x003d,"Multi-Link [RFC1717]" },
{ 0x003f,"NETBIOS Framing" },
{ 0x0041,"Cisco Systems" },
{ 0x0043,"Ascom Timeplex" },
{ 0x0045,"Fujitsu Link Backup and Load Balancing (LBLB)" },
{ 0x0047,"DCA Remote Lan" },
{ 0x0049,"Serial Data Transport Protocol (PPP-SDTP)" },
{ 0x004b,"SNA over 802.2" },
{ 0x004d,"SNA" },
{ 0x004f,"IP6 Header Compression" },
{ 0x0051,"KNX Bridging Data" },
{ 0x0053,"Encryption" },
{ 0x0055,"Individual Link Encryption" },
{ 0x006f,"Stampede Bridging" },
{ 0x00fb,"compression on single link in multilink group" },
{ 0x00fd,"1st choice compression" },
{ 0x0201,"802.1d Hello Packets" },
{ 0x0203,"IBM Source Routing BPDU" },
{ 0x0205,"DEC LANBridge100 Spanning Tree" },
{ 0x0207,"Cisco Discovery Protocol" },
{ 0x0209,"Netcs Twin Routing" },
{ 0x0231,"Luxcom" },
{ 0x0233,"Sigma Network Systems" },
{ 0x0235,"Apple Client Server Protocol" },
{ 0x4001,"Cray Communications Control Protocol" },
{ 0x4003,"CDPD Mobile Network Registration Protocol" },
{ 0x4021,"Stacker LZS" },
{ 0x8021,"Internet Protocol Control Protocol" },
{ 0x8023,"OSI Network Layer Control Protocol" },
{ 0x8025,"Xerox NS IDP Control Protocol" },
{ 0x8027,"DECnet Phase IV Control Protocol" },
{ 0x8029,"Appletalk Control Protocol" },
{ 0x802b,"Novell IPX Control Protocol" },
{ 0x8031,"Bridging NCP" },
{ 0x8033,"Stream Protocol Control Protocol" },
{ 0x8035,"Banyan Vines Control Protocol" },
{ 0x803d,"Multi-Link Control Protocol" },
{ 0x803f,"NETBIOS Framing Control Protocol" },
{ 0x8041,"Cisco Systems Control Protocol" },
{ 0x8043,"Ascom Timeplex" },
{ 0x8045,"Fujitsu LBLB Control Protocol" },
{ 0x8047,"DCA Remote Lan Network Control Protocol (RLNCP)" },
{ 0x8049,"Serial Data Control Protocol (PPP-SDCP)" },
{ 0x804b,"SNA over 802.2 Control Protocol" },
{ 0x804d,"SNA Control Protocol" },
{ 0x804f,"IP6 Header Compression Control Protocol" },
{ 0x8051,"KNX Bridging Control Protocol" },
{ 0x8053,"Encryption Control Protocol" },
{ 0x8055,"Individual Link Encryption Control Protocol" },
{ 0x806f,"Stampede Bridging Control Protocol" },
{ 0x80fb,"compression on single link in multilink group control" },
{ 0x80fd,"Compression Control Protocol" },
{ 0x8207,"Cisco Discovery Protocol Control" },
{ 0x8209,"Netcs Twin Routing" },
{ 0x8235,"Apple Client Server Protocol Control" },
{ 0xc021,"Link Control Protocol" },
{ 0xc023,"Password Authentication Protocol" },
{ 0xc025,"Link Quality Report" },
{ 0xc027,"Shiva Password Authentication Protocol" },
{ 0xc029,"CallBack Control Protocol (CBCP)" },
{ 0xc081,"Container Control Protocol" },
{ 0xc223,"Challenge Handshake Authentication Protocol" },
{ 0xc225,"RSA Authentication Protocol" },
{ 0xc26f,"Stampede Bridging Authorization Protocol" },
{ 0xc281,"Proprietary Authentication Protocol" },
{ 0xc283,"Proprietary Authentication Protocol" },
{ 0xc481,"Proprietary Node ID Authentication Protocol" }
};

1616
ipppd/sys-linux.c Normal file

File diff suppressed because it is too large Load Diff

619
ipppd/upap.c Normal file
View File

@ -0,0 +1,619 @@
/*
* upap.c - User/Password Authentication Protocol.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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 lint
static char rcsid[] = "$Id: upap.c,v 1.1 1997/03/07 16:01:41 hipp Exp $";
#endif
/*
* TODO:
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <syslog.h>
#include "fsm.h"
#include "pppd.h"
#include "upap.h"
extern int log_raw_password;
/*
* Protocol entry points.
*/
static void upap_init __P((int));
static void upap_lowerup __P((int));
static void upap_lowerdown __P((int));
static void upap_input __P((int, u_char *, int));
static void upap_protrej __P((int));
static int upap_printpkt __P((u_char *, int,
void (*) __P((void *, char *, ...)), void *));
struct protent pap_protent = {
PPP_PAP,
upap_init,
upap_input,
upap_protrej,
upap_lowerup,
upap_lowerdown,
NULL,
NULL,
upap_printpkt,
NULL,
1,
"PAP",
NULL,
NULL,
NULL
};
upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
static void upap_timeout __P((caddr_t));
static void upap_reqtimeout __P((caddr_t));
static void upap_rauthreq __P((upap_state *, u_char *, int, int));
static void upap_rauthack __P((upap_state *, u_char *, int, int));
static void upap_rauthnak __P((upap_state *, u_char *, int, int));
static void upap_sauthreq __P((upap_state *));
static void upap_sresp __P((upap_state *, int, int, char *, int));
/*
* upap_init - Initialize a UPAP unit.
*/
void
upap_init(unit)
int unit;
{
upap_state *u = &upap[unit];
u->us_unit = unit;
u->us_ruser[0] = 0;
u->us_ruserlen = 0;
u->us_rpasswd[0] = 0;
u->us_rpasswdlen = 0;
u->us_user = NULL;
u->us_userlen = 0;
u->us_passwd = NULL;
u->us_passwdlen = 0;
u->us_clientstate = UPAPCS_INITIAL;
u->us_serverstate = UPAPSS_INITIAL;
u->us_id = 0;
u->us_timeouttime = UPAP_DEFTIMEOUT;
u->us_maxtransmits = 10;
u->us_reqtimeout = UPAP_DEFREQTIME;
}
/*
* upap_authwithpeer - Authenticate us with our peer (start client).
*
* Set new state and send authenticate's.
*/
void upap_authwithpeer(int unit,char *user,char *password)
{
upap_state *u = &upap[unit];
/* Save the username and password we're given */
u->us_user = user;
u->us_userlen = strlen(user);
u->us_passwd = password;
u->us_passwdlen = strlen(password);
u->us_transmits = 0;
/* Lower layer up yet? */
if (u->us_clientstate == UPAPCS_INITIAL ||
u->us_clientstate == UPAPCS_PENDING) {
u->us_clientstate = UPAPCS_PENDING;
return;
}
upap_sauthreq(u); /* Start protocol */
}
/*
* upap_authpeer - Authenticate our peer (start server).
*
* Set new state.
*/
void upap_authpeer(int unit)
{
upap_state *u = &upap[unit];
/* Lower layer up yet? */
if (u->us_serverstate == UPAPSS_INITIAL ||
u->us_serverstate == UPAPSS_PENDING) {
u->us_serverstate = UPAPSS_PENDING;
return;
}
u->us_serverstate = UPAPSS_LISTEN;
if (u->us_reqtimeout > 0)
TIMEOUT(upap_reqtimeout, (caddr_t) u, u->us_reqtimeout);
}
/*
* upap_timeout - Retransmission timer for sending auth-reqs expired.
*/
static void upap_timeout(caddr_t arg)
{
upap_state *u = (upap_state *) arg;
if (u->us_clientstate != UPAPCS_AUTHREQ)
return;
if (u->us_transmits >= u->us_maxtransmits) {
/* give up in disgust */
syslog(LOG_ERR, "No response to PAP authenticate-requests");
u->us_clientstate = UPAPCS_BADAUTH;
auth_withpeer_fail(u->us_unit, PPP_PAP);
return;
}
upap_sauthreq(u); /* Send Authenticate-Request */
}
/*
* upap_reqtimeout - Give up waiting for the peer to send an auth-req.
*/
static void
upap_reqtimeout(arg)
caddr_t arg;
{
upap_state *u = (upap_state *) arg;
if (u->us_serverstate != UPAPSS_LISTEN)
return; /* huh?? */
auth_peer_fail(u->us_unit, PPP_PAP);
u->us_serverstate = UPAPSS_BADAUTH;
}
/*
* upap_lowerup - The lower layer is up.
*
* Start authenticating if pending.
*/
void upap_lowerup(int unit)
{
upap_state *u = &upap[unit];
if (u->us_clientstate == UPAPCS_INITIAL)
u->us_clientstate = UPAPCS_CLOSED;
else if (u->us_clientstate == UPAPCS_PENDING) {
upap_sauthreq(u); /* send an auth-request */
}
if (u->us_serverstate == UPAPSS_INITIAL)
u->us_serverstate = UPAPSS_CLOSED;
else if (u->us_serverstate == UPAPSS_PENDING) {
u->us_serverstate = UPAPSS_LISTEN;
if (u->us_reqtimeout > 0)
TIMEOUT(upap_reqtimeout, (caddr_t) u, u->us_reqtimeout);
}
}
/*
* upap_lowerdown - The lower layer is down.
*
* Cancel all timeouts.
*/
void upap_lowerdown(int unit)
{
upap_state *u = &upap[unit];
if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
UNTIMEOUT(upap_timeout, (caddr_t) u); /* Cancel timeout */
if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
UNTIMEOUT(upap_reqtimeout, (caddr_t) u);
u->us_clientstate = UPAPCS_INITIAL;
u->us_serverstate = UPAPSS_INITIAL;
}
/*
* upap_protrej - Peer doesn't speak this protocol.
*
* This shouldn't happen. In any case, pretend lower layer went down.
*/
void upap_protrej(int linkunit)
{
int unit = lns[linkunit].upap_unit;
upap_state *u = &upap[unit]; /* link unit! */
if (u->us_clientstate == UPAPCS_AUTHREQ) {
syslog(LOG_ERR, "PAP authentication failed due to protocol-reject");
auth_withpeer_fail(u->us_unit, PPP_PAP);
}
if (u->us_serverstate == UPAPSS_LISTEN) {
syslog(LOG_ERR, "PAP authentication of peer failed (protocol-reject)");
auth_peer_fail(u->us_unit, PPP_PAP);
}
upap_lowerdown(unit);
}
/*
* upap_input - Input UPAP packet.
*/
void upap_input(int linkunit,u_char *inpacket,int l)
{
int unit = lns[linkunit].upap_unit;
upap_state *u = &upap[unit];
u_char *inp;
u_char code, id;
int len;
/*
* Parse header (code, id and length).
* If packet too short, drop it.
*/
inp = inpacket;
if (l < UPAP_HEADERLEN) {
UPAPDEBUG((LOG_INFO, "upap_input: rcvd short header."));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len < UPAP_HEADERLEN) {
UPAPDEBUG((LOG_INFO, "upap_input: rcvd illegal length."));
return;
}
if (len > l) {
UPAPDEBUG((LOG_INFO, "upap_input: rcvd short packet."));
return;
}
len -= UPAP_HEADERLEN;
/*
* Action depends on code.
*/
switch (code) {
case UPAP_AUTHREQ:
upap_rauthreq(u, inp, id, len);
break;
case UPAP_AUTHACK:
upap_rauthack(u, inp, id, len);
break;
case UPAP_AUTHNAK:
upap_rauthnak(u, inp, id, len);
break;
default: /* XXX Need code reject */
break;
}
}
/*
* upap_rauth - Receive Authenticate.
*/
static void
upap_rauthreq(upap_state *u,u_char *inp,int id,int len)
{
u_char ruserlen, rpasswdlen;
char *ruser, *rpasswd;
int retcode;
char *msg;
int msglen;
UPAPDEBUG((LOG_INFO, "upap_rauth: Rcvd id %d.", id));
if (u->us_serverstate < UPAPSS_LISTEN)
return;
/*
* If we receive a duplicate authenticate-request, we are
* supposed to return the same status as for the first request.
*/
if (u->us_serverstate == UPAPSS_OPEN) {
upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
return;
}
if (u->us_serverstate == UPAPSS_BADAUTH) {
upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
return;
}
/*
* Parse user/passwd.
*/
if (len < sizeof (u_char)) {
UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet."));
return;
}
GETCHAR(ruserlen, inp);
len -= sizeof (u_char) + ruserlen + sizeof (u_char);
if (len < 0) {
UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet."));
return;
}
ruser = (char *) inp;
INCPTR(ruserlen, inp);
GETCHAR(rpasswdlen, inp);
if (len < rpasswdlen) {
UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet."));
return;
}
rpasswd = (char *) inp;
/*
* Check the username and password given.
*/
if(ruserlen > 64)
ruserlen = 64;
if(rpasswdlen > 64)
rpasswdlen = 64;
strncpy(u->us_ruser,ruser,(int)ruserlen);
strncpy(u->us_rpasswd,rpasswd,(int)rpasswdlen);
u->us_rpasswdlen = rpasswdlen;
u->us_ruserlen = ruserlen;
retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
rpasswdlen, &msg, &msglen);
upap_sresp(u, retcode, id, msg, msglen);
if (retcode == UPAP_AUTHACK) {
u->us_serverstate = UPAPSS_OPEN;
auth_peer_success(u->us_unit, PPP_PAP);
} else {
u->us_serverstate = UPAPSS_BADAUTH;
auth_peer_fail(u->us_unit, PPP_PAP);
}
if (u->us_reqtimeout > 0)
UNTIMEOUT(upap_reqtimeout, (caddr_t) u);
}
/*
* upap_rauthack - Receive Authenticate-Ack.
*/
static void
upap_rauthack(u, inp, id, len)
upap_state *u;
u_char *inp;
int id;
int len;
{
u_char msglen;
char *msg;
UPAPDEBUG((LOG_INFO, "upap_rauthack: Rcvd id %d.", id));
if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
return;
/*
* Parse message.
*/
if (len < sizeof (u_char)) {
UPAPDEBUG((LOG_INFO, "upap_rauthack: rcvd short packet."));
return;
}
GETCHAR(msglen, inp);
len -= sizeof (u_char);
if (len < msglen) {
UPAPDEBUG((LOG_INFO, "upap_rauthack: rcvd short packet."));
return;
}
msg = (char *) inp;
PRINTMSG(msg, msglen);
u->us_clientstate = UPAPCS_OPEN;
auth_withpeer_success(u->us_unit, PPP_PAP);
}
/*
* upap_rauthnak - Receive Authenticate-Nakk.
*/
static void
upap_rauthnak(u, inp, id, len)
upap_state *u;
u_char *inp;
int id;
int len;
{
u_char msglen;
char *msg;
UPAPDEBUG((LOG_INFO, "upap_rauthnak: Rcvd id %d.", id));
if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
return;
/*
* Parse message.
*/
if (len < sizeof (u_char)) {
UPAPDEBUG((LOG_INFO, "upap_rauthnak: rcvd short packet."));
return;
}
GETCHAR(msglen, inp);
len -= sizeof (u_char);
if (len < msglen) {
UPAPDEBUG((LOG_INFO, "upap_rauthnak: rcvd short packet."));
return;
}
msg = (char *) inp;
PRINTMSG(msg, msglen);
u->us_clientstate = UPAPCS_BADAUTH;
syslog(LOG_ERR, "PAP authentication failed");
auth_withpeer_fail(u->us_unit, PPP_PAP);
}
/*
* upap_sauthreq - Send an Authenticate-Request.
*/
static void
upap_sauthreq(u)
upap_state *u;
{
u_char *outp;
int outlen;
outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
u->us_userlen + u->us_passwdlen;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_PAP);
PUTCHAR(UPAP_AUTHREQ, outp);
PUTCHAR(++u->us_id, outp);
PUTSHORT(outlen, outp);
PUTCHAR(u->us_userlen, outp);
BCOPY(u->us_user, outp, u->us_userlen);
INCPTR(u->us_userlen, outp);
PUTCHAR(u->us_passwdlen, outp);
BCOPY(u->us_passwd, outp, u->us_passwdlen);
output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
UPAPDEBUG((LOG_INFO, "upap_sauth: Sent id %d.", u->us_id));
TIMEOUT(upap_timeout, (caddr_t) u, u->us_timeouttime);
++u->us_transmits;
u->us_clientstate = UPAPCS_AUTHREQ;
}
/*
* upap_sresp - Send a response (ack or nak).
*/
static void
upap_sresp(u, code, id, msg, msglen)
upap_state *u;
u_char code, id;
char *msg;
int msglen;
{
u_char *outp;
int outlen;
outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_PAP);
PUTCHAR(code, outp);
PUTCHAR(id, outp);
PUTSHORT(outlen, outp);
PUTCHAR(msglen, outp);
BCOPY(msg, outp, msglen);
output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
UPAPDEBUG((LOG_INFO, "upap_sresp: Sent code %d, id %d.", code, id));
}
/*
* upap_printpkt - print the contents of a PAP packet.
*/
char *upap_codenames[] = {
"AuthReq", "AuthAck", "AuthNak"
};
int
upap_printpkt(p, plen, printer, arg)
u_char *p;
int plen;
void (*printer) __P((void *, char *, ...));
void *arg;
{
int code, id, len;
int mlen, ulen, wlen;
char *user, *pwd, *msg;
u_char *pstart;
if (plen < UPAP_HEADERLEN)
return 0;
pstart = p;
GETCHAR(code, p);
GETCHAR(id, p);
GETSHORT(len, p);
if (len < UPAP_HEADERLEN || len > plen)
return 0;
if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *))
printer(arg, " %s", upap_codenames[code-1]);
else
printer(arg, " code=0x%x", code);
printer(arg, " id=0x%x", id);
len -= UPAP_HEADERLEN;
switch (code) {
case UPAP_AUTHREQ:
if (len < 1)
break;
ulen = p[0];
if (len < ulen + 2)
break;
wlen = p[ulen + 1];
if (len < ulen + wlen + 2)
break;
user = (char *) (p + 1);
pwd = (char *) (p + ulen + 2);
p += ulen + wlen + 2;
len -= ulen + wlen + 2;
printer(arg, " user=");
print_string(user, ulen, printer, arg);
if(log_raw_password) {
printer(arg, " password=");
print_string(pwd, wlen, printer, arg);
}
else
printer(arg, " password not logged for security reasons! Use '+pwlog' option to enable full logging.");
break;
case UPAP_AUTHACK:
case UPAP_AUTHNAK:
if (len < 1)
break;
mlen = p[0];
if (len < mlen + 1)
break;
msg = (char *) (p + 1);
p += mlen + 1;
len -= mlen + 1;
printer(arg, "msg=");
print_string(msg, mlen, printer, arg);
break;
}
/* print the rest of the bytes in the packet */
for (; len > 0; --len) {
GETCHAR(code, p);
printer(arg, " %.2x", code);
}
return p - pstart;
}

92
ipppd/upap.h Normal file
View File

@ -0,0 +1,92 @@
/*
* upap.h - User/Password Authentication Protocol definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id: upap.h,v 1.1 1997/03/07 16:01:42 hipp Exp $
*/
/*
* Packet header = Code, id, length.
*/
#define UPAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short))
/*
* UPAP codes.
*/
#define UPAP_AUTHREQ 1 /* Authenticate-Request */
#define UPAP_AUTHACK 2 /* Authenticate-Ack */
#define UPAP_AUTHNAK 3 /* Authenticate-Nak */
/*
* Each interface is described by upap structure.
*/
typedef struct upap_state {
int us_unit; /* Interface unit number */
char *us_user; /* User */
char us_ruser[64]; /* User */
int us_userlen; /* User length */
int us_ruserlen; /* User length */
char *us_passwd; /* Password */
char us_rpasswd[64]; /* Password */
int us_passwdlen; /* Password length */
int us_rpasswdlen; /* Password length */
int us_clientstate; /* Client state */
int us_serverstate; /* Server state */
u_char us_id; /* Current id */
int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */
int us_transmits; /* Number of auth-reqs sent */
int us_maxtransmits; /* Maximum number of auth-reqs to send */
int us_reqtimeout; /* Time to wait for auth-req from peer */
} upap_state;
/*
* Client states.
*/
#define UPAPCS_INITIAL 0 /* Connection down */
#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */
#define UPAPCS_PENDING 2 /* Connection down, have requested auth */
#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */
#define UPAPCS_OPEN 4 /* We've received an Ack */
#define UPAPCS_BADAUTH 5 /* We've received a Nak */
/*
* Server states.
*/
#define UPAPSS_INITIAL 0 /* Connection down */
#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */
#define UPAPSS_PENDING 2 /* Connection down, have requested auth */
#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */
#define UPAPSS_OPEN 4 /* We've sent an Ack */
#define UPAPSS_BADAUTH 5 /* We've sent a Nak */
/*
* Timeouts.
*/
#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */
#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */
extern upap_state upap[];
extern struct protent pap_protent;
void upap_authwithpeer __P((int, char *, char *));
void upap_authpeer __P((int));

32
ipppstats/Makefile Normal file
View File

@ -0,0 +1,32 @@
#
# pppstats makefile
# $Id: Makefile,v 1.1 1997/03/07 15:57:03 hipp Exp $
#
PPPSTATSRCS = ipppstats.c
PPPSTATOBJS = ipppstats.o
CC = gcc
COPTS = -O2
COMPILE_FLAGS = -m486 -fomit-frame-pointer -I../include
LIBS =
INSTALL= install -o root -g daemon
CFLAGS = $(COPTS) $(COMPILE_FLAGS)
all: ipppstats
install: ipppstats
$(INSTALL) -s -c ipppstats $(BINDIR)/ipppstats
$(INSTALL) -c -m 444 ipppstats.8 $(MANDIR)/man8/ipppstats.8
ipppstats: $(PPPSTATSRCS)
$(CC) $(CFLAGS) -o ipppstats ipppstats.c $(LIBS)
clean:
rm -f ipppstats *~ #* core
depend:
cpp -M $(CFLAGS) $(PPPSTATSRCS) >.depend
# makedepend $(CFLAGS) $(PPPSTATSRCS)

54
ipppstats/ipppstats.8 Normal file
View File

@ -0,0 +1,54 @@
.\" @(#) $Id: ipppstats.8,v 1.1 1997/03/07 15:57:04 hipp Exp $
.TH PPPSTATS 8 "2 May 1995"
.SH NAME
pppstats \- print PPP statistics
.SH SYNOPSIS
.B pppstats
[
.B -v
] [
.B -r
] [
.B -c
] [
.B -i
.I <secs>
] [
.I <unit#>
]
.ti 12
.SH DESCRIPTION
.B pppstats
prints PPP-related statistics.
.PP
The
.B -v
flag causes
.B pppstats
to display additional statistics, such as the number of packets tossed
(that is, which the VJ TCP header decompression code rejected).
.PP
The
.B -r
flag causes
.B pppstats
to display the overall packet compression rate. The rate value is
between 0 and 1, with 0 meaning that the data is incompressible.
.PP
The
.B -c
flag is used to specify an alternate display mode that shows
packet compression statistics: the number of packets and bytes
uncompressed (that is, before compression or after decompression),
compressed, and incompressible (packets which did not shrink on
compression and were transmitted uncompressed), and the recent
compression rate. This rate reflects the recent performance of the
compression code rather than the overall rate achieved since
compression was enabled.
.PP
The
.B -i
flag is used to specify the interval between printouts. The default is
5 seconds.
.PP
<unit#> specifies which interface to use for gathering statistics.

340
ipppstats/ipppstats.c Normal file
View File

@ -0,0 +1,340 @@
/*
* print PPP statistics:
* ipppstats [-i interval] [-v] [-r] [-c] [interface]
*
* -i <update interval in seconds>
* -v Verbose mode for default display
* -r Show compression ratio in default display
* -c Show Compression statistics instead of default display
* -a Do not show relative values. Show absolute values at all times.
*
*
* History:
* perkins@cps.msu.edu: Added compression statistics and alternate
* display. 11/94
* Brad Parker (brad@cayman.com) 6/92
*
* from the original "slstats" by Van Jaconson
*
* Copyright (c) 1989 Regents of the University of California.
* 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 the University of California, Berkeley. The name of the
* University 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.
*
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
* - Initial distribution.
*/
#ifndef lint
static char rcsid[] = "$Id: ipppstats.c,v 1.1 1997/03/07 15:57:05 hipp Exp $";
#endif
#include <ctype.h>
#include <errno.h>
#include <nlist.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/ppp_defs.h>
#include <sys/socket.h>
#include <linux/if.h>
#ifndef STREAMS
#include <linux/if_ppp.h> /* BSD, Linux, NeXT, etc. */
#else /* SunOS 4, AIX 4, OSF/1, etc. */
#define PPP_STATS 1 /* should be defined iff it is in ppp_if.c */
#include <sys/stream.h>
#include <linux/ppp_str.h>
#endif
int vflag, rflag, cflag, aflag;
unsigned interval = 5;
int unit;
int s; /* socket file descriptor */
int signalled; /* set if alarm goes off "early" */
extern char *malloc();
void catchalarm __P((int));
main(argc, argv)
int argc;
char *argv[];
{
--argc; ++argv;
while (argc > 0) {
if (strcmp(argv[0], "-a") == 0) {
++aflag;
++argv, --argc;
continue;
}
if (strcmp(argv[0], "-v") == 0) {
++vflag;
++argv, --argc;
continue;
}
if (strcmp(argv[0], "-r") == 0) {
++rflag;
++argv, --argc;
continue;
}
if (strcmp(argv[0], "-c") == 0) {
++cflag;
++argv, --argc;
continue;
}
if (strcmp(argv[0], "-i") == 0 && argv[1] &&
isdigit(argv[1][0])) {
interval = atoi(argv[1]);
if (interval < 0)
usage();
++argv, --argc;
++argv, --argc;
continue;
}
if (isdigit(argv[0][0])) {
unit = atoi(argv[0]);
if (unit < 0)
usage();
++argv, --argc;
continue;
}
usage();
}
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("couldn't create IP socket");
exit(1);
}
intpr();
exit(0);
}
usage()
{
fprintf(stderr, "Usage: ipppstats [-v] [-r] [-c] [-i interval] [unit]\n");
exit(1);
}
#define V(offset) (line % 20? cur.offset - old.offset: cur.offset)
#define W(offset) (line % 20? ccs.offset - ocs.offset: ccs.offset)
#define CRATE(comp, inc, unc) ((unc) == 0? 0.0: \
1.0 - (double)((comp) + (inc)) / (unc))
/*
* Print a running summary of interface statistics.
* Repeat display every interval seconds, showing statistics
* collected over that interval. Assumes that interval is non-zero.
* First line printed at top of screen is always cumulative.
*/
intpr()
{
register int line = 0;
sigset_t oldmask, mask;
struct ppp_stats cur, old;
struct ppp_comp_stats ccs, ocs;
memset(&old, 0, sizeof(old));
memset(&ocs, 0, sizeof(ocs));
while (1) {
get_ppp_stats(&cur);
if (cflag || rflag)
get_ppp_cstats(&ccs);
(void)signal(SIGALRM, catchalarm);
signalled = 0;
(void)alarm(interval);
if ((line % 20) == 0) {
if (line > 0)
putchar('\n');
if (cflag) {
printf("%6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s",
"ubyte", "upack", "cbyte", "cpack", "ibyte", "ipack", "ratio");
printf(" | %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s",
"ubyte", "upack", "cbyte", "cpack", "ibyte", "ipack", "ratio");
putchar('\n');
} else {
printf("%6.6s %6.6s %6.6s %6.6s %6.6s",
"in", "pack", "comp", "uncomp", "err");
if (vflag)
printf(" %6.6s %6.6s", "toss", "ip");
if (rflag)
printf(" %6.6s %6.6s", "ratio", "ubyte");
printf(" | %6.6s %6.6s %6.6s %6.6s %6.6s",
"out", "pack", "comp", "uncomp", "ip");
if (vflag)
printf(" %6.6s %6.6s", "search", "miss");
if(rflag)
printf(" %6.6s %6.6s", "ratio", "ubyte");
putchar('\n');
}
memset(&old, 0, sizeof(old));
memset(&ocs, 0, sizeof(ocs));
}
if (cflag) {
printf("%6d %6d %6d %6d %6d %6d %6.2f",
W(d.unc_bytes),
W(d.unc_packets),
W(d.comp_bytes),
W(d.comp_packets),
W(d.inc_bytes),
W(d.inc_packets),
W(d.ratio) == 0? 0.0: 1 - 1.0 / W(d.ratio) * 256.0);
printf(" | %6d %6d %6d %6d %6d %6d %6.2f",
W(c.unc_bytes),
W(c.unc_packets),
W(c.comp_bytes),
W(c.comp_packets),
W(c.inc_bytes),
W(c.inc_packets),
W(d.ratio) == 0? 0.0: 1 - 1.0 / W(d.ratio) * 256.0);
putchar('\n');
} else {
printf("%6d %6d %6d %6d %6d",
V(p.ppp_ibytes),
V(p.ppp_ipackets), V(vj.vjs_compressedin),
V(vj.vjs_uncompressedin), V(vj.vjs_errorin));
if (vflag)
printf(" %6d %6d", V(vj.vjs_tossed),
V(p.ppp_ipackets) - V(vj.vjs_compressedin) -
V(vj.vjs_uncompressedin) - V(vj.vjs_errorin));
if (rflag)
printf(" %6.2f %6d",
CRATE(W(d.comp_bytes), W(d.unc_bytes), W(d.unc_bytes)),
W(d.unc_bytes));
printf(" | %6d %6d %6d %6d %6d", V(p.ppp_obytes),
V(p.ppp_opackets), V(vj.vjs_compressed),
V(vj.vjs_packets) - V(vj.vjs_compressed),
V(p.ppp_opackets) - V(vj.vjs_packets));
if (vflag)
printf(" %6d %6d", V(vj.vjs_searches), V(vj.vjs_misses));
if (rflag)
printf(" %6.2f %6d",
CRATE(W(d.comp_bytes), W(d.unc_bytes), W(d.unc_bytes)),
W(c.unc_bytes));
putchar('\n');
}
fflush(stdout);
line++;
if (interval == 0)
exit(0);
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
sigprocmask(SIG_BLOCK, &mask, &oldmask);
if (! signalled) {
sigemptyset(&mask);
sigsuspend(&mask);
}
sigprocmask(SIG_SETMASK, &oldmask, NULL);
signalled = 0;
(void)alarm(interval);
if (aflag==0) {
old = cur;
ocs = ccs;
}
}
}
/*
* Called if an interval expires before sidewaysintpr has completed a loop.
* Sets a flag to not wait for the alarm.
*/
void catchalarm(arg)
int arg;
{
signalled = 1;
}
get_ppp_stats(curp)
struct ppp_stats *curp;
{
struct ifpppstatsreq req;
memset (&req, 0, sizeof (req));
req.stats_ptr = (caddr_t) &req.stats;
#undef ifr_name
#define ifr_name ifr__name
sprintf(req.ifr_name, "ippp%d", unit);
if (ioctl(s, SIOCGPPPSTATS, &req) < 0) {
if (errno == ENOTTY)
fprintf(stderr, "ipppstats: kernel support missing\n");
else
perror("ioctl(SIOCGPPPSTATS)");
exit(1);
}
*curp = req.stats;
}
get_ppp_cstats(csp)
struct ppp_comp_stats *csp;
{
struct ifpppcstatsreq creq;
memset (&creq, 0, sizeof (creq));
creq.stats_ptr = (caddr_t) &creq.stats;
#undef ifr_name
#define ifr_name ifr__name
sprintf(creq.ifr_name, "ippp%d", unit);
if (ioctl(s, SIOCGPPPCSTATS, &creq) < 0) {
if (errno == ENOTTY) {
fprintf(stderr, "ipppstats: no kernel compression support\n");
if (cflag)
exit(1);
rflag = 0;
} else {
perror("ioctl(SIOCGPPPCSTATS)");
exit(1);
}
}
if (creq.stats.c.bytes_out == 0)
creq.stats.c.ratio = 0.0;
else
creq.stats.c.ratio = (double) creq.stats.c.in_count /
(double) creq.stats.c.bytes_out;
if (creq.stats.d.bytes_out == 0)
creq.stats.d.ratio = 0.0;
else
creq.stats.d.ratio = (double) creq.stats.d.in_count /
(double) creq.stats.d.bytes_out;
*csp = creq.stats;
}