diff options
author | joshd <joshd@cvs.openbsd.org> | 1996-07-20 12:02:16 +0000 |
---|---|---|
committer | joshd <joshd@cvs.openbsd.org> | 1996-07-20 12:02:16 +0000 |
commit | d1ca06e9f2af777503835fcef79a3827eef02cd2 (patch) | |
tree | 0a8b89f672dd48513d85694a0f63e93191380c82 /usr.sbin | |
parent | b9db315696088975891987c416c6eafdbed087eb (diff) |
Update pppd to 2.3a4:
Add redo option error-reporting, add PAM, add microsoft compatibility
kludges, bzero stuff at important places, add one or two options
other generic enhancements. From: Paul.Mackerras@cs.anu.edu.au
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/pppd/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/pppd/auth.c | 322 | ||||
-rw-r--r-- | usr.sbin/pppd/ccp.c | 126 | ||||
-rw-r--r-- | usr.sbin/pppd/ccp.h | 15 | ||||
-rw-r--r-- | usr.sbin/pppd/chap.c | 74 | ||||
-rw-r--r-- | usr.sbin/pppd/chap.h | 11 | ||||
-rw-r--r-- | usr.sbin/pppd/chap_ms.c | 184 | ||||
-rw-r--r-- | usr.sbin/pppd/chap_ms.h | 32 | ||||
-rw-r--r-- | usr.sbin/pppd/demand.c | 37 | ||||
-rw-r--r-- | usr.sbin/pppd/fsm.c | 20 | ||||
-rw-r--r-- | usr.sbin/pppd/ipcp.c | 118 | ||||
-rw-r--r-- | usr.sbin/pppd/ipcp.h | 12 | ||||
-rw-r--r-- | usr.sbin/pppd/ipxcp.c | 1394 | ||||
-rw-r--r-- | usr.sbin/pppd/ipxcp.h | 64 | ||||
-rw-r--r-- | usr.sbin/pppd/lcp.c | 100 | ||||
-rw-r--r-- | usr.sbin/pppd/lcp.h | 9 | ||||
-rw-r--r-- | usr.sbin/pppd/main.c | 418 | ||||
-rw-r--r-- | usr.sbin/pppd/md4.c | 295 | ||||
-rw-r--r-- | usr.sbin/pppd/md4.h | 52 | ||||
-rw-r--r-- | usr.sbin/pppd/options.c | 214 | ||||
-rw-r--r-- | usr.sbin/pppd/patchlevel.h | 6 | ||||
-rw-r--r-- | usr.sbin/pppd/pathnames.h | 4 | ||||
-rw-r--r-- | usr.sbin/pppd/pppd.h | 75 | ||||
-rw-r--r-- | usr.sbin/pppd/upap.c | 51 | ||||
-rw-r--r-- | usr.sbin/pppd/upap.h | 9 |
25 files changed, 3340 insertions, 306 deletions
diff --git a/usr.sbin/pppd/Makefile b/usr.sbin/pppd/Makefile index 65c24f33248..f8552ded808 100644 --- a/usr.sbin/pppd/Makefile +++ b/usr.sbin/pppd/Makefile @@ -1,10 +1,10 @@ -# $OpenBSD: Makefile,v 1.5 1996/05/29 19:14:37 deraadt Exp $ +# $OpenBSD: Makefile,v 1.6 1996/07/20 12:02:03 joshd Exp $ # $NetBSD: Makefile,v 1.12 1996/03/19 03:03:04 jtc Exp $ PROG= pppd SRCS= main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ auth.c options.c sys-bsd.c demand.c gencode.c grammar.c scanner.c \ - nametoaddr.c optimize.c bpf_filter.c + nametoaddr.c optimize.c bpf_filter.c chap_ms.c ipxcp.c md4.c .PATH: ${.CURDIR}/../../lib/libpcap ${.CURDIR}/../../sys/net MAN= pppd.8 SUBDIR= pppstats chat diff --git a/usr.sbin/pppd/auth.c b/usr.sbin/pppd/auth.c index 458a8f90612..765e2c7ba60 100644 --- a/usr.sbin/pppd/auth.c +++ b/usr.sbin/pppd/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.3 1996/04/21 23:41:16 deraadt Exp $ */ +/* $OpenBSD: auth.c,v 1.4 1996/07/20 12:02:04 joshd Exp $ */ /* * auth.c - PPP authentication and phase control. @@ -35,7 +35,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: auth.c,v 1.3 1996/04/21 23:41:16 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: auth.c,v 1.4 1996/07/20 12:02:04 joshd Exp $"; #endif #include <stdio.h> @@ -53,6 +53,11 @@ static char rcsid[] = "$OpenBSD: auth.c,v 1.3 1996/04/21 23:41:16 deraadt Exp $" #include <netinet/in.h> #include <arpa/inet.h> +#ifdef USE_PAM +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#endif + #ifdef HAS_SHADOW #include <shadow.h> #include <shadow/pwauth.h> @@ -88,12 +93,18 @@ struct wordlist { #define FALSE 0 #define TRUE 1 +/* The name by which the peer authenticated itself to us. */ +char peer_authname[MAXNAMELEN]; + /* Records which authentication operations haven't completed yet. */ static int auth_pending[NUM_PPP]; /* Set if we have successfully called login() */ static int logged_in; +/* Set if we have run the /etc/ppp/auth-up script. */ +static int did_authup; + /* List of addresses which the peer may use. */ static struct wordlist *addresses[NUM_PPP]; @@ -103,6 +114,9 @@ static int num_np_open; /* Number of network protocols which have come up. */ static int num_np_up; +/* Set if we got the contents of passwd[] from the pap-secrets file. */ +static int passwd_from_file; + /* Bits in auth_pending[] */ #define UPAP_WITHPEER 1 #define UPAP_PEER 2 @@ -116,13 +130,15 @@ static void check_idle __P((caddr_t)); static int login __P((char *, char *, char **, int *)); static void logout __P((void)); static int null_login __P((int)); -static int get_upap_passwd __P((void)); +static int get_upap_passwd __P((char *)); static int have_upap_secret __P((void)); static int have_chap_secret __P((char *, char *, u_int32_t)); static int ip_addr_check __P((u_int32_t, struct wordlist *)); static int scan_authfile __P((FILE *, char *, char *, u_int32_t, char *, struct wordlist **, char *)); static void free_wordlist __P((struct wordlist *)); +static void auth_script __P((char *)); + /* * An Open on LCP has requested a change from Dead to Establish phase. @@ -160,6 +176,10 @@ link_down(unit) int i; struct protent *protp; + if (did_authup) { + auth_script(_PATH_AUTHDOWN); + did_authup = 0; + } for (i = 0; (protp = protocols[i]) != NULL; ++i) { if (!protp->enabled_flag) continue; @@ -167,6 +187,7 @@ link_down(unit) (*protp->lowerdown)(unit); if (protp->protocol < 0xC000 && protp->close != NULL) (*protp->close)(unit, "LCP link down"); + } num_np_open = 0; num_np_up = 0; @@ -223,6 +244,11 @@ link_established(unit) ChapAuthWithPeer(unit, our_name, ho->chap_mdtype); auth |= CHAP_WITHPEER; } else if (ho->neg_upap) { + if (passwd[0] == 0) { + passwd_from_file = 1; + if (!get_upap_passwd(passwd)) + syslog(LOG_ERR, "No secret found for PAP login"); + } upap_authwithpeer(unit, user, passwd); auth |= UPAP_WITHPEER; } @@ -241,10 +267,21 @@ network_phase(unit) { int i; struct protent *protp; + lcp_options *go = &lcp_gotoptions[unit]; + + /* + * If the peer had to authenticate, run the auth-up script now. + */ + if ((go->neg_chap || go->neg_upap) && !did_authup) { + auth_script(_PATH_AUTHUP); + did_authup = 1; + } phase = PHASE_NETWORK; +#if 0 if (!demand) set_filters(&pass_filter, &active_filter); +#endif for (i = 0; (protp = protocols[i]) != NULL; ++i) if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) { @@ -272,8 +309,10 @@ auth_peer_fail(unit, protocol) * The peer has been successfully authenticated using `protocol'. */ void -auth_peer_success(unit, protocol) +auth_peer_success(unit, protocol, name, namelen) int unit, protocol; + char *name; + int namelen; { int bit; @@ -291,6 +330,14 @@ auth_peer_success(unit, protocol) } /* + * Save the authenticated name of the peer for later. + */ + if (namelen > sizeof(peer_authname) - 1) + namelen = sizeof(peer_authname) - 1; + BCOPY(name, peer_authname, namelen); + peer_authname[namelen] = 0; + + /* * If there is no more authentication still to be done, * proceed to the network phase. */ @@ -305,6 +352,9 @@ void auth_withpeer_fail(unit, protocol) int unit, protocol; { + if (passwd_from_file) + BZERO(passwd, MAXSECRETLEN); + /* * We've failed to authenticate ourselves to our peer. * He'll probably take the link down, and there's not much @@ -326,6 +376,8 @@ auth_withpeer_success(unit, protocol) bit = CHAP_WITHPEER; break; case PPP_PAP: + if (passwd_from_file) + BZERO(passwd, MAXSECRETLEN); bit = UPAP_WITHPEER; break; default: @@ -411,6 +463,7 @@ void auth_check_options() { lcp_options *wo = &lcp_wantoptions[0]; + int can_auth; lcp_options *ao = &lcp_allowoptions[0]; ipcp_options *ipwo = &ipcp_wantoptions[0]; u_int32_t remote; @@ -431,7 +484,7 @@ auth_check_options() * Check whether we have appropriate secrets to use * to authenticate ourselves and/or the peer. */ - if (ao->neg_upap && passwd[0] == 0 && !get_upap_passwd()) + if (ao->neg_upap && passwd[0] == 0 && !get_upap_passwd(passwd)) ao->neg_upap = 0; if (wo->neg_upap && !uselogin && !have_upap_secret()) wo->neg_upap = 0; @@ -451,6 +504,34 @@ pppd: peer authentication required but no suitable secret(s) found\n"); } +/* + * auth_reset - called when LCP is starting negotiations to recheck + * authentication options, i.e. whether we have appropriate secrets + * to use for authenticating ourselves and/or the peer. + */ +void +auth_reset(unit) + int unit; +{ + lcp_options *go = &lcp_gotoptions[unit]; + lcp_options *ao = &lcp_allowoptions[0]; + ipcp_options *ipwo = &ipcp_wantoptions[0]; + u_int32_t remote; + + ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_upap_passwd(NULL)); + ao->neg_chap = !refuse_chap + && have_chap_secret(our_name, remote_name, (u_int32_t)0); + + if (go->neg_upap && !uselogin && !have_upap_secret()) + go->neg_upap = 0; + if (go->neg_chap) { + remote = ipwo->accept_remote? 0: ipwo->hisaddr; + if (!have_chap_secret(remote_name, our_name, remote)) + go->neg_chap = 0; + } + +} + /* * check_passwd - Check the user name and passwd against the PAP secrets @@ -489,6 +570,8 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) passwd[passwdlen] = '\0'; BCOPY(auser, user, userlen); user[userlen] = '\0'; + *msg = (char *) 0; + /* * Open the file of upap secrets and scan for a suitable secret @@ -525,7 +608,8 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) } if (ret == UPAP_AUTHNAK) { - *msg = "Login incorrect"; + if (*msg == (char *) 0) + *msg = "Login incorrect"; *msglen = strlen(*msg); /* * Frustrate passwd stealer programs. @@ -544,16 +628,94 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) } else { attempts = 0; /* Reset count */ - *msg = "Login ok"; + if (*msg == (char *) 0) + *msg = "Login ok"; *msglen = strlen(*msg); if (addresses[unit] != NULL) free_wordlist(addresses[unit]); addresses[unit] = addrs; } + BZERO(passwd, sizeof(passwd)); + BZERO(secret, sizeof(secret)); + return ret; } +#ifdef HAS_SHADOW +/************** + * This function was lifted from the shadow-3.3.2 version by John Haugh II. + * It is included because the function was not in the standard libshadow + * library. If it is included in the library then I can remove it from here. + */ + +#define DAY (24L*3600L) +/* + * isexpired - determine if account is expired yet + * + * isexpired calculates the expiration date based on the + * password expiration criteria. + */ + +/*ARGSUSED*/ +int +isexpired (pw, sp) +struct passwd *pw; +struct spwd *sp; +{ + long clock; + + clock = time ((time_t *) 0) / DAY; + + /* + * 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 < clock) + return 3; + + if (sp->sp_inact > 0 && sp->sp_lstchg > 0 && sp->sp_max > 0 && + sp->sp_inact + sp->sp_lstchg + sp->sp_max < clock) + 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) + 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 < clock) + return 1; + + return 0; +} +#endif + +/* + * This function is needed for PAM. However, it should not be called. + * If it is, return the error code. + */ + +#ifdef USE_PAM +static int pam_conv(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr) +{ + return PAM_CONV_ERR; +} +#endif + /* * login - Check the user name and password against the system @@ -564,6 +726,7 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) * UPAP_AUTHACK: Login succeeded. * In either case, msg points to an appropriate message. */ + static int login(user, passwd, msg, msglen) char *user; @@ -571,46 +734,101 @@ login(user, passwd, msg, msglen) char **msg; int *msglen; { - struct passwd *pw; - char *epasswd; char *tty; +#ifdef USE_PAM + struct pam_conv pam_conversation; + pam_handle_t *pamh; + int pam_error; + char *pass; + char *dev; +/* + * Fill the pam_conversion structure + */ + memset (&pam_conversation, '\0', sizeof (struct pam_conv)); + pam_conversation.conv = &pam_conv; + + pam_error = pam_start ("ppp", user, &pam_conversation, &pamh); + if (pam_error != PAM_SUCCESS) { + *msg = (char *) pam_strerror (pam_error); + return UPAP_AUTHNAK; + } +/* + * Define the fields for the credintial validation + */ + (void) pam_set_item (pamh, PAM_AUTHTOK, passwd); + (void) pam_set_item (pamh, PAM_TTY, devnam); +/* + * Validate the user + */ + pam_error = pam_authenticate (pamh, PAM_SILENT); + if (pam_error == PAM_SUCCESS) + pam_error = pam_acct_mgmt (pamh, PAM_SILENT); + + *msg = (char *) pam_strerror (pam_error); +/* + * Clean up the mess + */ + (void) pam_end (pamh, pam_error); + + if (pam_error != PAM_SUCCESS) + return UPAP_AUTHNAK; +/* + * Use the non-PAM methods directly + */ +#else /* #ifdef USE_PAM */ + + struct passwd *pw; + char *epasswd; + #ifdef HAS_SHADOW struct spwd *spwd; struct spwd *getspnam(); #endif - + if ((pw = getpwnam(user)) == NULL) { - return (UPAP_AUTHNAK); - } - -#ifdef HAS_SHADOW - if ((spwd = getspnam(user)) == NULL) { + return (UPAP_AUTHNAK); + } + +#ifdef HAS_SHADOW + if ((spwd = getspnam(user)) == NULL) { pw->pw_passwd = ""; } else { - pw->pw_passwd = spwd->sp_pwdp; + pw->pw_passwd = spwd->sp_pwdp; } #endif - + /* * XXX If no passwd, let them login without one. */ if (pw->pw_passwd == '\0') { - return (UPAP_AUTHACK); - } - -#ifdef HAS_SHADOW - if ((pw->pw_passwd && pw->pw_passwd[0] == '@' - && pw_auth (pw->pw_passwd+1, pw->pw_name, PW_PPP, NULL)) - || !valid (passwd, pw)) { - return (UPAP_AUTHNAK); + return (UPAP_AUTHACK); + } + +#ifdef HAS_SHADOW + if (pw->pw_passwd) { + if (pw->pw_passwd[0] == '@') { + if (pw_auth (pw->pw_passwd+1, pw->pw_name, PW_PPP, NULL)) { + return (UPAP_AUTHNAK); + } + } else { + epasswd = pw_encrypt(passwd, pw->pw_passwd); + if (strcmp(epasswd, pw->pw_passwd)) { + return (UPAP_AUTHNAK); + } + } + /* check the age of the password entry */ + if (spwd && (isexpired (pw, spwd) != 0)) { + return (UPAP_AUTHNAK); + } } #else epasswd = crypt(passwd, pw->pw_passwd); if (strcmp(epasswd, pw->pw_passwd)) { - return (UPAP_AUTHNAK); + return (UPAP_AUTHNAK); } #endif +#endif /* #ifdef USE_PAM */ syslog(LOG_INFO, "user %s logged in", user); @@ -670,6 +888,7 @@ null_login(unit) i = scan_authfile(f, "", our_name, (u_int32_t)0, secret, &addrs, filename); ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0; + BZERO(secret, sizeof(secret)); if (ret) { if (addresses[unit] != NULL) @@ -688,7 +907,8 @@ null_login(unit) * could be found. */ static int -get_upap_passwd() +get_upap_passwd(passwd) +char *passwd; { char *filename; FILE *f; @@ -701,11 +921,15 @@ get_upap_passwd() if (f == NULL) return 0; check_access(f, filename); - if (scan_authfile(f, user, remote_name, (u_int32_t)0, - secret, NULL, filename) < 0) + if (scan_authfile(f, user, + remote_name[0]? remote_name: NULL, + (u_int32_t)0, secret, NULL, filename) < 0) return 0; - strncpy(passwd, secret, MAXSECRETLEN); - passwd[MAXSECRETLEN-1] = 0; + if (passwd != NULL) { + strncpy(passwd, secret, MAXSECRETLEN); + passwd[MAXSECRETLEN-1] = 0; + } + BZERO(secret, sizeof(secret)); return 1; } @@ -910,7 +1134,7 @@ ip_addr_check(addr, addrs) if (ptr_mask != NULL) *ptr_mask = '/'; - if (a == 0xffffffff) + if (a == -1L) syslog (LOG_WARNING, "unknown host %s in auth. address list", addrs->word); @@ -1121,3 +1345,37 @@ free_wordlist(wp) wp = next; } } + +/* + * auth_script - execute a script with arguments + * interface-name peer-name real-user tty speed + */ +static void +auth_script(script) + char *script; +{ + char strspeed[32]; + struct passwd *pw; + char struid[32]; + char *user_name; + char *argv[8]; + + if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL) + user_name = pw->pw_name; + else { + sprintf(struid, "%d", getuid()); + user_name = struid; + } + sprintf(strspeed, "%d", baud_rate); + + argv[0] = script; + argv[1] = ifname; + argv[2] = peer_authname; + argv[3] = user_name; + argv[4] = devnam; + argv[5] = strspeed; + argv[6] = NULL; + + run_program(script, argv, 0); +} + diff --git a/usr.sbin/pppd/ccp.c b/usr.sbin/pppd/ccp.c index 074ab4a70e7..dab6a1d676a 100644 --- a/usr.sbin/pppd/ccp.c +++ b/usr.sbin/pppd/ccp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ccp.c,v 1.3 1996/04/21 23:41:18 deraadt Exp $ */ +/* $OpenBSD: ccp.c,v 1.4 1996/07/20 12:02:05 joshd Exp $ */ /* * ccp.c - PPP Compression Control Protocol. @@ -28,7 +28,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: ccp.c,v 1.3 1996/04/21 23:41:18 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: ccp.c,v 1.4 1996/07/20 12:02:05 joshd Exp $"; #endif #include <string.h> @@ -40,10 +40,37 @@ static char rcsid[] = "$OpenBSD: ccp.c,v 1.3 1996/04/21 23:41:18 deraadt Exp $"; #include "fsm.h" #include "ccp.h" +/* + * Protocol entry points from main code. + */ +static void ccp_init __P((int unit)); +static void ccp_open __P((int unit)); +static void ccp_close __P((int unit, char *)); +static void ccp_lowerup __P((int unit)); +static void ccp_lowerdown __P((int)); +static void ccp_input __P((int unit, u_char *pkt, int len)); +static void ccp_protrej __P((int unit)); +static int ccp_printpkt __P((u_char *pkt, int len, + void (*printer) __P((void *, char *, ...)), + void *arg)); +static void ccp_datainput __P((int unit, u_char *pkt, int len)); + struct protent ccp_protent = { - PPP_CCP, ccp_init, ccp_input, ccp_protrej, - ccp_lowerup, ccp_lowerdown, ccp_open, ccp_close, - ccp_printpkt, ccp_datainput, 1, "CCP", NULL, NULL + PPP_CCP, + ccp_init, + ccp_input, + ccp_protrej, + ccp_lowerup, + ccp_lowerdown, + ccp_open, + ccp_close, + ccp_printpkt, + ccp_datainput, + 1, + "CCP", + NULL, + NULL, + NULL }; fsm ccp_fsm[NUM_PPP]; @@ -105,7 +132,7 @@ static int all_rejected[NUM_PPP]; /* we rejected all peer's options */ /* * ccp_init - initialize CCP. */ -void +static void ccp_init(unit) int unit; { @@ -160,7 +187,7 @@ ccp_open(unit) /* * ccp_close - Terminate CCP. */ -void +static void ccp_close(unit, reason) int unit; char *reason; @@ -172,7 +199,7 @@ ccp_close(unit, reason) /* * ccp_lowerup - we may now transmit CCP packets. */ -void +static void ccp_lowerup(unit) int unit; { @@ -182,7 +209,7 @@ ccp_lowerup(unit) /* * ccp_lowerdown - we may not transmit CCP packets. */ -void +static void ccp_lowerdown(unit) int unit; { @@ -192,7 +219,7 @@ ccp_lowerdown(unit) /* * ccp_input - process a received CCP packet. */ -void +static void ccp_input(unit, p, len) int unit; u_char *p; @@ -254,7 +281,7 @@ ccp_extcode(f, code, id, p, len) /* * ccp_protrej - peer doesn't talk CCP. */ -void +static void ccp_protrej(unit) int unit; { @@ -402,6 +429,8 @@ ccp_addci(f, p, lenp) } } + go->method = (p > p0)? p0[0]: -1; + *lenp = p - p0; } @@ -613,6 +642,7 @@ ccp_reqci(f, p, lenp, dont_nak) len = *lenp; memset(ho, 0, sizeof(ccp_options)); + ho->method = (len > 0)? p[0]: -1; while (len > 0) { newret = CONFACK; @@ -765,6 +795,42 @@ ccp_reqci(f, p, lenp, dont_nak) } /* + * Make a string name for a compression method (or 2). + */ +static char * +method_name(opt, opt2) + ccp_options *opt, *opt2; +{ + static char result[64]; + + if (!ANY_COMPRESS(*opt)) + return "(none)"; + switch (opt->method) { + case CI_DEFLATE: + if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) + sprintf(result, "Deflate (%d/%d)", opt->deflate_size, + opt2->deflate_size); + else + sprintf(result, "Deflate (%d)", opt->deflate_size); + break; + case CI_BSD_COMPRESS: + if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) + sprintf(result, "BSD-Compress (%d/%d)", opt->bsd_bits, + opt2->bsd_bits); + else + sprintf(result, "BSD-Compress (%d)", opt->bsd_bits); + break; + case CI_PREDICTOR_1: + return "Predictor 1"; + case CI_PREDICTOR_2: + return "Predictor 2"; + default: + sprintf(result, "Method %d", opt->method); + } + return result; +} + +/* * CCP has come up - inform the kernel driver. */ static void @@ -774,12 +840,26 @@ ccp_up(f) ccp_options *go = &ccp_gotoptions[f->unit]; ccp_options *ho = &ccp_hisoptions[f->unit]; + char method1[64]; + ccp_flags_set(f->unit, 1, 1); - if (ANY_COMPRESS(*go) || ANY_COMPRESS(*ho)) - syslog(LOG_NOTICE, "%s enabled", - ANY_COMPRESS(*go)? ANY_COMPRESS(*ho)? "Compression": - "Receive compression": "Transmit compression"); -} + if (ANY_COMPRESS(*go)) { + if (ANY_COMPRESS(*ho)) { + if (go->method == ho->method) { + syslog(LOG_NOTICE, "%s compression enabled", + method_name(go, ho)); + } else { + strcpy(method1, method_name(go, NULL)); + syslog(LOG_NOTICE, "%s / %s compression enabled", + method1, method_name(ho, NULL)); + } + } else + syslog(LOG_NOTICE, "%s receive compression enabled", + method_name(go, NULL)); + } else + syslog(LOG_NOTICE, "%s transmit compression enabled", + method_name(ho, NULL)); +} /* * CCP has gone down - inform the kernel driver. @@ -797,14 +877,14 @@ ccp_down(f) /* * Print the contents of a CCP packet. */ -char *ccp_codenames[] = { +static char *ccp_codenames[] = { "ConfReq", "ConfAck", "ConfNak", "ConfRej", "TermReq", "TermAck", "CodeRej", NULL, NULL, NULL, NULL, NULL, NULL, "ResetReq", "ResetAck", }; -int +static int ccp_printpkt(p, plen, printer, arg) u_char *p; int plen; @@ -883,6 +963,16 @@ ccp_printpkt(p, plen, printer, arg) printer(arg, ">"); } break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + } /* dump out the rest of the packet in hex */ diff --git a/usr.sbin/pppd/ccp.h b/usr.sbin/pppd/ccp.h index 4907e636098..95bf811035f 100644 --- a/usr.sbin/pppd/ccp.h +++ b/usr.sbin/pppd/ccp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ccp.h,v 1.2 1996/03/25 15:55:33 niklas Exp $ */ +/* $OpenBSD: ccp.h,v 1.3 1996/07/20 12:02:05 joshd Exp $ */ /* * ccp.h - Definitions for PPP Compression Control Protocol. @@ -34,6 +34,7 @@ typedef struct ccp_options { 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[]; @@ -42,16 +43,4 @@ extern ccp_options ccp_gotoptions[]; extern ccp_options ccp_allowoptions[]; extern ccp_options ccp_hisoptions[]; -void ccp_init __P((int unit)); -void ccp_open __P((int unit)); -void ccp_close __P((int unit, char *)); -void ccp_lowerup __P((int unit)); -void ccp_lowerdown __P((int)); -void ccp_input __P((int unit, u_char *pkt, int len)); -void ccp_protrej __P((int unit)); -int ccp_printpkt __P((u_char *pkt, int len, - void (*printer) __P((void *, char *, ...)), - void *arg)); -void ccp_datainput __P((int unit, u_char *pkt, int len)); - extern struct protent ccp_protent; diff --git a/usr.sbin/pppd/chap.c b/usr.sbin/pppd/chap.c index fa081cc7ae4..a91bf2c38fe 100644 --- a/usr.sbin/pppd/chap.c +++ b/usr.sbin/pppd/chap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: chap.c,v 1.2 1996/03/25 15:55:35 niklas Exp $ */ +/* $OpenBSD: chap.c,v 1.3 1996/07/20 12:02:06 joshd Exp $ */ /* * chap.c - Crytographic Handshake Authentication Protocol. @@ -21,7 +21,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: chap.c,v 1.2 1996/03/25 15:55:35 niklas Exp $"; +static char rcsid[] = "$OpenBSD: chap.c,v 1.3 1996/07/20 12:02:06 joshd Exp $"; #endif /* @@ -38,12 +38,41 @@ static char rcsid[] = "$OpenBSD: chap.c,v 1.2 1996/03/25 15:55:35 niklas Exp $"; #include "chap.h" #include "md5.h" +#ifdef CHAPMS +#include "chap_ms.h" +#endif + +/* + * 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 + 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)); @@ -63,7 +92,7 @@ extern void srand48 __P((long)); /* * ChapInit - Initialize a CHAP unit. */ -void +static void ChapInit(unit) int unit; { @@ -205,7 +234,7 @@ ChapRechallenge(arg) * * Start up if we have pending requests. */ -void +static void ChapLowerUp(unit) int unit; { @@ -231,7 +260,7 @@ ChapLowerUp(unit) * * Cancel all timeouts. */ -void +static void ChapLowerDown(unit) int unit; { @@ -255,7 +284,7 @@ ChapLowerDown(unit) /* * ChapProtocolReject - Peer doesn't grok CHAP. */ -void +static void ChapProtocolReject(unit) int unit; { @@ -274,7 +303,7 @@ ChapProtocolReject(unit) /* * ChapInput - Input CHAP packet. */ -void +static void ChapInput(unit, inpacket, packet_len) int unit; u_char *inpacket; @@ -378,8 +407,15 @@ ChapReceiveChallenge(cstate, inp, id, len) 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)); + + /* Microsoft doesn't send their name back in the PPP packet */ + if (rhostname[0] == 0 && cstate->resp_type == CHAP_MICROSOFT) { + strcpy(rhostname, remote_name); + CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name", + rhostname)); + } /* get secret for authenticating ourselves with the specified host */ if (!get_secret(cstate->unit, cstate->resp_name, rhostname, @@ -409,11 +445,18 @@ ChapReceiveChallenge(cstate, inp, id, len) cstate->resp_length = MD5_SIGNATURE_SIZE; break; +#ifdef CHAPMS + case CHAP_MICROSOFT: + ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len); + break; +#endif + default: CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->resp_type)); return; } + BZERO(secret, sizeof(secret)); ChapSendResponse(cstate); } @@ -518,13 +561,14 @@ ChapReceiveResponse(cstate, inp, id, len) } } + BZERO(secret, sizeof(secret)); 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); + auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len); } if (cstate->chal_interval != 0) TIMEOUT(ChapRechallenge, (caddr_t) cstate, cstate->chal_interval); @@ -745,11 +789,11 @@ ChapSendResponse(cstate) /* * ChapPrintPkt - print the contents of a CHAP packet. */ -char *ChapCodenames[] = { +static char *ChapCodenames[] = { "Challenge", "Response", "Success", "Failure" }; -int +static int ChapPrintPkt(p, plen, printer, arg) u_char *p; int plen; diff --git a/usr.sbin/pppd/chap.h b/usr.sbin/pppd/chap.h index 45f1e3d2f3b..2f57d434ed1 100644 --- a/usr.sbin/pppd/chap.h +++ b/usr.sbin/pppd/chap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: chap.h,v 1.3 1996/06/16 14:35:49 deraadt Exp $ */ +/* $OpenBSD: chap.h,v 1.4 1996/07/20 12:02:06 joshd Exp $ */ /* * chap.h - Challenge-Handshake Authentication Protocol definitions. @@ -29,6 +29,8 @@ #define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */ #define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */ +#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */ +#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ #define CHAP_CHALLENGE 1 #define CHAP_RESPONSE 2 @@ -98,15 +100,8 @@ typedef struct chap_state { extern chap_state chap[]; -void ChapInit __P((int)); void ChapAuthWithPeer __P((int, char *, int)); void ChapAuthPeer __P((int, char *, int)); -void ChapLowerUp __P((int)); -void ChapLowerDown __P((int)); -void ChapInput __P((int, u_char *, int)); -void ChapProtocolReject __P((int)); -int ChapPrintPkt __P((u_char *, int, - void (*) __P((void *, char *, ...)), void *)); extern struct protent chap_protent; diff --git a/usr.sbin/pppd/chap_ms.c b/usr.sbin/pppd/chap_ms.c new file mode 100644 index 00000000000..096b649ff6c --- /dev/null +++ b/usr.sbin/pppd/chap_ms.c @@ -0,0 +1,184 @@ +/* + * 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. + */ + +#ifndef lint +static char rcsid[] = "$Id: chap_ms.c,v 1.1 1996/07/20 12:02:06 joshd 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" + + +#ifdef CHAPMS +#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; +/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse), + in case this struct gets padded. */ + + +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 /* CHAPMS */ + + +void +ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len) + chap_state *cstate; + char *rchallenge; + int rchallenge_len; + char *secret; + int secret_len; +{ +#ifdef CHAPMS + 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 /* CHAPMS */ +} diff --git a/usr.sbin/pppd/chap_ms.h b/usr.sbin/pppd/chap_ms.h new file mode 100644 index 00000000000..6697cba328d --- /dev/null +++ b/usr.sbin/pppd/chap_ms.h @@ -0,0 +1,32 @@ +/* + * chap.h - Challenge 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 1996/07/20 12:02:07 joshd 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 --git a/usr.sbin/pppd/demand.c b/usr.sbin/pppd/demand.c index 0292ca43020..d57f12db57a 100644 --- a/usr.sbin/pppd/demand.c +++ b/usr.sbin/pppd/demand.c @@ -1,4 +1,4 @@ -/* $OpenBSD: demand.c,v 1.1 1996/03/25 15:55:37 niklas Exp $ */ +/* $OpenBSD: demand.c,v 1.2 1996/07/20 12:02:07 joshd Exp $ */ /* * demand.c - Dial on demand support. @@ -20,7 +20,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: demand.c,v 1.1 1996/03/25 15:55:37 niklas Exp $"; +static char rcsid[] = "$OpenBSD: demand.c,v 1.2 1996/07/20 12:02:07 joshd Exp $"; #endif #include <stdio.h> @@ -62,6 +62,8 @@ struct packet { struct packet *pend_q; struct packet *pend_qtail; +static int active_packet __P((unsigned char *, int)); + /* * demand_conf - configure the interface for doing dial-on-demand. */ @@ -87,7 +89,9 @@ demand_conf() ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0); ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0); +#if 0 set_filters(&pass_filter, &active_filter); +#endif /* * Call the demand_conf procedure for each protocol that's got one. @@ -310,3 +314,32 @@ demand_rexmit(proto) if (prev != NULL) prev->next = NULL; } + +/* + * Scan a packet to decide whether it is an "active" packet, + * that is, whether it is worth bringing up the link for. + */ +static int +active_packet(p, len) + unsigned char *p; + int len; +{ + int proto, i; + struct protent *protp; + + if (len < PPP_HDRLEN) + return 0; + proto = PPP_PROTOCOL(p); + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { + if (!protp->enabled_flag) + return 0; + if (protp->active_pkt == NULL) + return 1; + return (*protp->active_pkt)(p, len); + } + } + return 0; /* not a supported protocol !!?? */ +} + + diff --git a/usr.sbin/pppd/fsm.c b/usr.sbin/pppd/fsm.c index 1347659263a..af467df0807 100644 --- a/usr.sbin/pppd/fsm.c +++ b/usr.sbin/pppd/fsm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fsm.c,v 1.2 1996/03/25 15:55:38 niklas Exp $ */ +/* $OpenBSD: fsm.c,v 1.3 1996/07/20 12:02:08 joshd Exp $ */ /* * fsm.c - {Link, IP} Control Protocol Finite State Machine. @@ -20,7 +20,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: fsm.c,v 1.2 1996/03/25 15:55:38 niklas Exp $"; +static char rcsid[] = "$OpenBSD: fsm.c,v 1.3 1996/07/20 12:02:08 joshd Exp $"; #endif /* @@ -43,7 +43,7 @@ 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)); +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)); @@ -349,7 +349,7 @@ fsm_input(f, inpacket, l) break; case TERMREQ: - fsm_rtermreq(f, id); + fsm_rtermreq(f, id, inp, len); break; case TERMACK: @@ -566,10 +566,14 @@ fsm_rconfnakrej(f, code, id, inp, len) * fsm_rtermreq - Receive Terminate-Req. */ static void -fsm_rtermreq(f, id) +fsm_rtermreq(f, id, p, len) 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)); @@ -580,7 +584,11 @@ fsm_rtermreq(f, id) break; case OPENED: - syslog(LOG_INFO, "%s terminated at peer's request", PROTO_NAME(f)); + 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; diff --git a/usr.sbin/pppd/ipcp.c b/usr.sbin/pppd/ipcp.c index 2ad4123751b..3532480a81b 100644 --- a/usr.sbin/pppd/ipcp.c +++ b/usr.sbin/pppd/ipcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipcp.c,v 1.2 1996/03/25 15:55:43 niklas Exp $ */ +/* $OpenBSD: ipcp.c,v 1.3 1996/07/20 12:02:08 joshd Exp $ */ /* * ipcp.c - PPP IP Control Protocol. @@ -20,7 +20,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: ipcp.c,v 1.2 1996/03/25 15:55:43 niklas Exp $"; +static char rcsid[] = "$OpenBSD: ipcp.c,v 1.3 1996/07/20 12:02:08 joshd Exp $"; #endif /* @@ -31,9 +31,13 @@ static char rcsid[] = "$OpenBSD: ipcp.c,v 1.2 1996/03/25 15:55:43 niklas Exp $"; #include <string.h> #include <syslog.h> #include <netdb.h> +#include <sys/param.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> #include "pppd.h" #include "fsm.h" @@ -86,13 +90,41 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ "IPCP" /* String name of protocol */ }; +/* + * Protocol entry points from main code. + */ +static void ipcp_init __P((int)); +static void ipcp_open __P((int)); +static void ipcp_close __P((int, char *)); +static void ipcp_lowerup __P((int)); +static void ipcp_lowerdown __P((int)); +static void ipcp_input __P((int, u_char *, int)); +static void ipcp_protrej __P((int)); +static int ipcp_printpkt __P((u_char *, int, + void (*) __P((void *, char *, ...)), void *)); +static void ip_check_options __P((void)); +static int ip_demand_conf __P((int)); +static int ip_active_pkt __P((u_char *, int)); + struct protent ipcp_protent = { - PPP_IPCP, ipcp_init, ipcp_input, ipcp_protrej, - ipcp_lowerup, ipcp_lowerdown, ipcp_open, ipcp_close, - ipcp_printpkt, NULL, 1, "IPCP", - ip_check_options, ip_demand_conf, + PPP_IPCP, + ipcp_init, + ipcp_input, + ipcp_protrej, + ipcp_lowerup, + ipcp_lowerdown, + ipcp_open, + ipcp_close, + ipcp_printpkt, + NULL, + 1, + "IPCP", + ip_check_options, + ip_demand_conf, + ip_active_pkt }; + /* * Lengths of configuration options. */ @@ -130,7 +162,7 @@ u_int32_t ipaddr; /* * ipcp_init - Initialize IPCP. */ -void +static void ipcp_init(unit) int unit; { @@ -173,7 +205,7 @@ ipcp_init(unit) /* * ipcp_open - IPCP is allowed to come up. */ -void +static void ipcp_open(unit) int unit; { @@ -184,7 +216,7 @@ ipcp_open(unit) /* * ipcp_close - Take IPCP down. */ -void +static void ipcp_close(unit, reason) int unit; char *reason; @@ -196,7 +228,7 @@ ipcp_close(unit, reason) /* * ipcp_lowerup - The lower layer is up. */ -void +static void ipcp_lowerup(unit) int unit; { @@ -207,7 +239,7 @@ ipcp_lowerup(unit) /* * ipcp_lowerdown - The lower layer is down. */ -void +static void ipcp_lowerdown(unit) int unit; { @@ -218,7 +250,7 @@ ipcp_lowerdown(unit) /* * ipcp_input - Input IPCP packet. */ -void +static void ipcp_input(unit, p, len) int unit; u_char *p; @@ -233,7 +265,7 @@ ipcp_input(unit, p, len) * * Pretend the lower layer went down, so we shut up. */ -void +static void ipcp_protrej(unit) int unit; { @@ -1007,7 +1039,7 @@ endswitch: * ip_check_options - check that any IP-related options are OK, * and assign appropriate defaults. */ -void +static void ip_check_options() { struct hostent *hp; @@ -1049,7 +1081,7 @@ ip_check_options() * ip_demand_conf - configure the interface as though * IPCP were up, for use with dial-on-demand. */ -int +static int ip_demand_conf(u) int u; { @@ -1155,6 +1187,8 @@ ipcp_up(f) return; } + sifnpmode(f->unit, PPP_IP, NPMODE_PASS); + /* assign a default route through the interface if required */ if (ipcp_wantoptions[f->unit].default_route) if (sifdefaultroute(f->unit, ho->hisaddr)) @@ -1190,8 +1224,9 @@ ipcp_down(f) { u_int32_t ouraddr, hisaddr; - np_down(f->unit, PPP_IP); IPCPDEBUG((LOG_INFO, "ipcp: down")); + np_down(f->unit, PPP_IP); + sifvjcomp(f->unit, 0, 0, 0); /* * If we are doing dial-on-demand, set the interface @@ -1261,16 +1296,16 @@ ipcp_script(f, script) /* * ipcp_printpkt - print the contents of an IPCP packet. */ -char *ipcp_codenames[] = { +static char *ipcp_codenames[] = { "ConfReq", "ConfAck", "ConfNak", "ConfRej", "TermReq", "TermAck", "CodeRej" }; -int +static int ipcp_printpkt(p, plen, printer, arg) u_char *p; int plen; - void (*printer)(); + void (*printer) __P((void *, char *, ...)); void *arg; { int code, id, len, olen; @@ -1351,6 +1386,16 @@ ipcp_printpkt(p, plen, printer, arg) printer(arg, ">"); } break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; } /* print the rest of the bytes in the packet */ @@ -1361,3 +1406,38 @@ ipcp_printpkt(p, plen, printer, arg) return p - pstart; } + +/* + * ip_active_pkt - see if this IP packet is worth bringing the link up +for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#ifndef IP_OFFMASK +#define IP_OFFMASK 0x1fff +#endif + +ip_active_pkt(pkt, len) + u_char *pkt; + int len; +{ + struct ip *ip; + struct tcphdr *tcp; + int hlen; + + if (len < sizeof(struct ip) + PPP_HDRLEN) + return 0; + ip = (struct ip *) (pkt + PPP_HDRLEN); + if ((ntohs(ip->ip_off) & IP_OFFMASK) != 0) + return 0; + if (ip->ip_p != IPPROTO_TCP) + return 1; + hlen = ip->ip_hl * 4; + if (len < hlen + sizeof(struct tcphdr) + PPP_HDRLEN) + return 0; + tcp = (struct tcphdr *) (pkt + PPP_HDRLEN + hlen); + if ((tcp->th_flags & TH_FIN) != 0 && hlen + tcp->th_off * 4 == len) + return 0; + return 1; +} + diff --git a/usr.sbin/pppd/ipcp.h b/usr.sbin/pppd/ipcp.h index ce7fe8ba7ef..9b54252b76f 100644 --- a/usr.sbin/pppd/ipcp.h +++ b/usr.sbin/pppd/ipcp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ipcp.h,v 1.2 1996/03/25 15:55:44 niklas Exp $ */ +/* $OpenBSD: ipcp.h,v 1.3 1996/07/20 12:02:09 joshd Exp $ */ /* * ipcp.h - IP Control Protocol definitions. @@ -62,16 +62,6 @@ extern ipcp_options ipcp_gotoptions[]; extern ipcp_options ipcp_allowoptions[]; extern ipcp_options ipcp_hisoptions[]; -void ipcp_init __P((int)); -void ipcp_open __P((int)); -void ipcp_close __P((int, char *)); -void ipcp_lowerup __P((int)); -void ipcp_lowerdown __P((int)); -void ipcp_input __P((int, u_char *, int)); -void ipcp_protrej __P((int)); -int ipcp_printpkt __P((u_char *, int, void (*)(), void *)); -void ip_check_options __P((void)); -int ip_demand_conf __P((int)); char *ip_ntoa __P((u_int32_t)); extern struct protent ipcp_protent; diff --git a/usr.sbin/pppd/ipxcp.c b/usr.sbin/pppd/ipxcp.c new file mode 100644 index 00000000000..39f57b36afd --- /dev/null +++ b/usr.sbin/pppd/ipxcp.c @@ -0,0 +1,1394 @@ +/* + * ipxcp.c - PPP IPX Control 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. + */ + +#ifdef IPX_CHANGE +#ifndef lint +static char rcsid[] = "$Id: ipxcp.c,v 1.1 1996/07/20 12:02:09 joshd Exp $"; +#endif + +/* + * TODO: + */ + +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#include "pppd.h" +#include "fsm.h" +#include "ipxcp.h" +#include "pathnames.h" + +/* global vars */ +ipxcp_options ipxcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +ipxcp_options ipxcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +ipxcp_options ipxcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +ipxcp_options ipxcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ + +#define wo (&ipxcp_wantoptions[0]) +#define ao (&ipxcp_allowoptions[0]) +#define go (&ipxcp_gotoptions[0]) +#define ho (&ipxcp_hisoptions[0]) + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipxcp_resetci __P((fsm *)); /* Reset our CI */ +static int ipxcp_cilen __P((fsm *)); /* Return length of our CI */ +static void ipxcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */ +static int ipxcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */ +static int ipxcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */ +static int ipxcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ +static int ipxcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ +static void ipxcp_up __P((fsm *)); /* We're UP */ +static void ipxcp_down __P((fsm *)); /* We're DOWN */ +static void ipxcp_script __P((fsm *, char *)); /* Run an up/down script */ + +fsm ipxcp_fsm[NUM_PPP]; /* IPXCP fsm structure */ + +static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */ + ipxcp_resetci, /* Reset our Configuration Information */ + ipxcp_cilen, /* Length of our Configuration Information */ + ipxcp_addci, /* Add our Configuration Information */ + ipxcp_ackci, /* ACK our Configuration Information */ + ipxcp_nakci, /* NAK our Configuration Information */ + ipxcp_rejci, /* Reject our Configuration Information */ + ipxcp_reqci, /* Request peer's Configuration Information */ + ipxcp_up, /* Called when fsm reaches OPENED state */ + ipxcp_down, /* Called when fsm leaves OPENED state */ + NULL, /* Called when we want the lower layer up */ + NULL, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPXCP" /* String name of protocol */ +}; + +/* + * Protocol entry points. + */ + +static void ipxcp_init __P((int)); +static void ipxcp_open __P((int)); +static void ipxcp_close __P((int, char *)); +static void ipxcp_lowerup __P((int)); +static void ipxcp_lowerdown __P((int)); +static void ipxcp_input __P((int, u_char *, int)); +static void ipxcp_protrej __P((int)); +static int ipxcp_printpkt __P((u_char *, int, + void (*) __P((void *, char *, ...)), void *)); + +struct protent ipxcp_protent = { + PPP_IPXCP, + ipxcp_init, + ipxcp_input, + ipxcp_protrej, + ipxcp_lowerup, + ipxcp_lowerdown, + ipxcp_open, + ipxcp_close, + ipxcp_printpkt, + NULL, + 0, + "IPXCP", + NULL, + NULL, + NULL +}; + + +/* + * Lengths of configuration options. + */ + +#define CILEN_VOID 2 +#define CILEN_COMPLETE 2 /* length of complete option */ +#define CILEN_NETN 6 /* network number length option */ +#define CILEN_NODEN 8 /* node number length option */ +#define CILEN_PROTOCOL 4 /* Minimum length of routing protocol */ +#define CILEN_NAME 3 /* Minimum length of router name */ +#define CILEN_COMPRESS 4 /* Minimum length of compression protocol */ + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +/* Used in printing the node number */ +#define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5] + +/* Used to generate the proper bit mask */ +#define BIT(num) (1 << (num)) + +/* + * Make a string representation of a network IP address. + */ + +char * +ipx_ntoa(ipxaddr) +u_int32_t ipxaddr; +{ + static char b[64]; + sprintf(b, "%lx", ipxaddr); + return b; +} + + +/* + * ipxcp_init - Initialize IPXCP. + */ +static void +ipxcp_init(unit) + int unit; +{ + fsm *f = &ipxcp_fsm[unit]; + + f->unit = unit; + f->protocol = PPP_IPXCP; + f->callbacks = &ipxcp_callbacks; + fsm_init(&ipxcp_fsm[unit]); + + memset (wo->name, 0, sizeof (wo->name)); + memset (wo->our_node, 0, sizeof (wo->our_node)); + memset (wo->his_node, 0, sizeof (wo->his_node)); + + wo->neg_nn = 1; + wo->neg_complete = 1; + wo->network = 0; + + ao->neg_node = 1; + ao->neg_nn = 1; + ao->neg_name = 1; + ao->neg_complete = 1; + ao->neg_router = 1; + + ao->accept_local = 0; + ao->accept_remote = 0; + ao->accept_network = 0; +} + +/* + * Copy the node number + */ + +static void +copy_node (src, dst) +u_char *src, *dst; +{ + memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node)); +} + +/* + * Compare node numbers + */ + +static int +compare_node (src, dst) +u_char *src, *dst; +{ + return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0; +} + +/* + * Is the node number zero? + */ + +static int +zero_node (node) +u_char *node; +{ + int indx; + for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx) + if (node [indx] != 0) + return 0; + return 1; +} + +/* + * Increment the node number + */ + +static void +inc_node (node) +u_char *node; +{ + u_char *outp; + u_int32_t magic_num; + + outp = node; + magic_num = magic(); + *outp++ = '\0'; + *outp++ = '\0'; + PUTLONG (magic_num, outp); +} + +/* + * ipxcp_open - IPXCP is allowed to come up. + */ +static void +ipxcp_open(unit) + int unit; +{ + fsm_open(&ipxcp_fsm[unit]); +} + +/* + * ipxcp_close - Take IPXCP down. + */ +static void +ipxcp_close(unit, reason) + int unit; + char *reason; +{ + fsm_close(&ipxcp_fsm[unit], reason); +} + + +/* + * ipxcp_lowerup - The lower layer is up. + */ +static void +ipxcp_lowerup(unit) + int unit; +{ + fsm_lowerup(&ipxcp_fsm[unit]); +} + + +/* + * ipxcp_lowerdown - The lower layer is down. + */ +static void +ipxcp_lowerdown(unit) + int unit; +{ + fsm_lowerdown(&ipxcp_fsm[unit]); +} + + +/* + * ipxcp_input - Input IPXCP packet. + */ +static void +ipxcp_input(unit, p, len) + int unit; + u_char *p; + int len; +{ + fsm_input(&ipxcp_fsm[unit], p, len); +} + + +/* + * ipxcp_protrej - A Protocol-Reject was received for IPXCP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void +ipxcp_protrej(unit) + int unit; +{ + fsm_lowerdown(&ipxcp_fsm[unit]); +} + + +/* + * ipxcp_resetci - Reset our CI. + */ +static void +ipxcp_resetci(f) + fsm *f; +{ + u_int32_t network; + int unit = f->unit; + + wo->req_node = wo->neg_node && ao->neg_node; + wo->req_nn = wo->neg_nn && ao->neg_nn; + + if (wo->our_network == 0) { + wo->neg_node = 1; + ao->accept_network = 1; + } +/* + * If our node number is zero then change it. + */ + if (zero_node (wo->our_node)) { + inc_node (wo->our_node); + ao->accept_local = 1; + wo->neg_node = 1; + } +/* + * If his node number is zero then change it. + */ + if (zero_node (wo->his_node)) { + inc_node (wo->his_node); + ao->accept_remote = 1; + } +/* + * Unless router protocol is suppressed then assume that we can do RIP. + */ + if (! (wo->router & BIT(0))) + wo->router |= BIT(2); +/* + * Router protocol is only negotiated if requested. Others force the + * negotiation. + */ + if (wo->router & (BIT(2) | BIT(4))) + wo->neg_router = 1; +/* + * Start with these default values + */ + *go = *wo; +} + +/* + * ipxcp_cilen - Return length of our CI. + */ +static int +ipxcp_cilen(f) + fsm *f; +{ + int unit = f->unit; + int len; + + len = go->neg_nn ? CILEN_NETN : 0; + len += go->neg_node ? CILEN_NODEN : 0; + len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0; + len += go->neg_complete ? CILEN_COMPLETE : 0; +/* + * Router protocol 0 is mutually exclusive with the others. + */ + if (go->neg_router) { + if (go->router & BIT(0)) + len += CILEN_PROTOCOL; + else { + if (go->router & BIT(2)) + len += CILEN_PROTOCOL; + if (go->router & BIT(4)) + len += CILEN_PROTOCOL; + } + } + + return (len); +} + + +/* + * ipxcp_addci - Add our desired CIs to a packet. + */ +static void +ipxcp_addci(f, ucp, lenp) + fsm *f; + u_char *ucp; + int *lenp; +{ + int len = *lenp; + int unit = f->unit; +/* + * Add the options to the record. + */ + if (go->neg_nn) { + PUTCHAR (IPX_NETWORK_NUMBER, ucp); + PUTCHAR (CILEN_NETN, ucp); + PUTLONG (go->our_network, ucp); + } + + if (go->neg_node) { + int indx; + PUTCHAR (IPX_NODE_NUMBER, ucp); + PUTCHAR (CILEN_NODEN, ucp); + for (indx = 0; indx < sizeof (go->our_node); ++indx) + PUTCHAR (go->our_node[indx], ucp); + } + + if (go->neg_name) { + int cilen = strlen (go->name); + int indx; + PUTCHAR (IPX_ROUTER_NAME, ucp); + PUTCHAR (CILEN_NAME + cilen - 1, ucp); + for (indx = 0; indx < cilen; ++indx) + PUTCHAR (go->name [indx], ucp); + } + + if (go->neg_router && (go->router & (BIT(0) | BIT(2) | BIT(4)))) { + if (go->router & BIT(0)) { + PUTCHAR (IPX_ROUTER_PROTOCOL, ucp); + PUTCHAR (CILEN_PROTOCOL, ucp); + PUTSHORT (0, ucp); + } else { + if (go->router & BIT(2)) { + PUTCHAR (IPX_ROUTER_PROTOCOL, ucp); + PUTCHAR (CILEN_PROTOCOL, ucp); + PUTSHORT (2, ucp); + } + + if (go->router & BIT(4)) { + PUTCHAR (IPX_ROUTER_PROTOCOL, ucp); + PUTCHAR (CILEN_PROTOCOL, ucp); + PUTSHORT (4, ucp); + } + } + } + + if (go->neg_complete) { + PUTCHAR (IPX_COMPLETE, ucp); + PUTCHAR (CILEN_COMPLETE, ucp); + } +} + +/* + * ipxcp_ackci - Ack our CIs. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int +ipxcp_ackci(f, p, len) + fsm *f; + u_char *p; + int len; +{ + int unit = f->unit; + u_short cilen, citype, cishort; + u_char cichar; + u_int32_t cilong; + +#define ACKCIVOID(opt, neg) \ + if (neg) { \ + if ((len -= CILEN_VOID) < 0) \ + break; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_VOID || \ + citype != opt) \ + break; \ + } + +#define ACKCICOMPLETE(opt,neg) ACKCIVOID(opt, neg) + +#define ACKCICHARS(opt, neg, val, cnt) \ + if (neg) { \ + int indx, count = cnt; \ + len -= (count + 2); \ + if (len < 0) \ + break; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != (count + 2) || \ + citype != opt) \ + break; \ + for (indx = 0; indx < count; ++indx) {\ + GETCHAR(cichar, p); \ + if (cichar != ((u_char *) &val)[indx]) \ + break; \ + }\ + if (indx != count) \ + break; \ + } + +#define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val)) +#define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val)) + +#define ACKCINETWORK(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_NETN) < 0) \ + break; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_NETN || \ + citype != opt) \ + break; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + break; \ + } + +#define ACKCIPROTO(opt, neg, val, bit) \ + if (neg && (val & BIT(bit))) \ + { \ + if (len < 2) \ + break; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_PROTOCOL || citype != opt) \ + break; \ + len -= cilen; \ + if (len < 0) \ + break; \ + GETSHORT(cishort, p); \ + if (cishort != (bit)) \ + break; \ + } +/* + * Process the ACK frame in the order in which the frame was assembled + */ + do { + ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network); + ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node); + ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name); + ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 0); + ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 2); + ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 4); + ACKCICOMPLETE (IPX_COMPLETE, go->neg_complete); +/* + * This is the end of the record. + */ + if (len == 0) + return (1); + } while (0); +/* + * The frame is invalid + */ + IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!")); + return (0); +} + +/* + * ipxcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPXCP is in the OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ + +static int +ipxcp_nakci(f, p, len) + fsm *f; + u_char *p; + int len; +{ + int unit = f->unit; + u_char citype, cilen, *next; + u_short s; + u_int32_t l; + ipxcp_options no; /* options we've seen Naks for */ + ipxcp_options try; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try = *go; + + while (len > CILEN_VOID) { + GETCHAR (citype, p); + GETCHAR (cilen, p); + len -= cilen; + if (len < 0) + goto bad; + next = &p [cilen - CILEN_VOID]; + + switch (citype) { + case IPX_NETWORK_NUMBER: + if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN)) + goto bad; + no.neg_nn = 1; + + GETLONG(l, p); + IPXCPDEBUG((LOG_INFO, "local IP address %d", l)); + if (l && ao->accept_network) + try.our_network = l; + break; + + case IPX_NODE_NUMBER: + if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN)) + goto bad; + no.neg_node = 1; + + IPXCPDEBUG((LOG_INFO, + "local node number %02X%02X%02X%02X%02X%02X", + NODE(p))); + + if (!zero_node (p) && ao->accept_local && + ! compare_node (p, ho->his_node)) + copy_node (p, try.our_node); + break; + + /* These have never been sent. Ignore the NAK frame */ + case IPX_COMPRESSION_PROTOCOL: + goto bad; + + case IPX_ROUTER_PROTOCOL: + if (!go->neg_router || (cilen < CILEN_PROTOCOL)) + goto bad; + + GETSHORT (s, p); + if ((s != 0) && (s != 2) && (s != 4)) + goto bad; + + if (no.router & BIT(s)) + goto bad; + + if (no.router == 0) /* Reset on first NAK only */ + try.router = 0; + no.router |= BIT(s); + try.router |= BIT(s); + try.neg_router = 1; + + IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s)); + break; + + /* These, according to the RFC, must never be NAKed. */ + case IPX_ROUTER_NAME: + case IPX_COMPLETE: + goto bad; + + /* These are for options which we have not seen. */ + default: + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) + goto bad; + + /* + * Do not permit the peer to force a router protocol which we do not + * support. + */ + try.router &= go->router; + if (try.router == 0 && go->router != 0) { + try.neg_router = 1; + try.router = BIT(0); + } + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != OPENED) + *go = try; + + return 1; + +bad: + IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!")); + return 0; +} + +/* + * ipxcp_rejci - Reject some of our CIs. + */ +static int +ipxcp_rejci(f, p, len) + fsm *f; + u_char *p; + int len; +{ + int unit = f->unit; + u_short cilen, citype, cishort; + u_char cichar; + u_int32_t cilong; + ipxcp_options try; /* options to request next time */ + +#define REJCINETWORK(opt, neg, val) \ + if (neg) { \ + neg = 0; \ + if ((len -= CILEN_NETN) < 0) \ + break; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_NETN || \ + citype != opt) \ + break; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + break; \ + IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \ + } + +#define REJCICHARS(opt, neg, val, cnt) \ + if (neg) { \ + int indx, count = cnt; \ + neg = 0; \ + len -= (count + 2); \ + if (len < 0) \ + break; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != (count + 2) || \ + citype != opt) \ + break; \ + for (indx = 0; indx < count; ++indx) {\ + GETCHAR(cichar, p); \ + if (cichar != ((u_char *) &val)[indx]) \ + break; \ + }\ + if (indx != count) \ + break; \ + IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \ + } + +#define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val)) +#define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val)) + +#define REJCIVOID(opt, neg) \ + if (neg) { \ + neg = 0; \ + if ((len -= CILEN_VOID) < 0) \ + break; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_VOID || citype != opt) \ + break; \ + IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \ + } + +#define REJCIPROTO(opt, neg, val, bit) \ + if (neg && (val & BIT(bit))) \ + { \ + if (len < 2) \ + break; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_PROTOCOL || citype != opt) \ + break; \ + len -= cilen; \ + if (len < 0) \ + break; \ + GETSHORT(cishort, p); \ + if (cishort != (bit)) \ + break; \ + IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected router proto %d", bit)); \ + val &= ~BIT(bit); \ + if (val == 0) \ + neg = 0; \ + } + +/* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + try = *go; + + do { + REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network); + REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node); + REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0); + REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 2); + REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 4); + REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name); + REJCIVOID (IPX_COMPLETE, try.neg_complete); +/* + * This is the end of the record. + */ + if (len == 0) { + if (f->state != OPENED) + *go = try; + return (1); + } + } while (0); +/* + * The frame is invalid at this point. + */ + IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!")); + return 0; +} + +/* + * ipxcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + */ +static int +ipxcp_reqci(f, inp, len, reject_if_disagree) + fsm *f; + u_char *inp; /* Requested CIs */ + int *len; /* Length of requested CIs */ + int reject_if_disagree; +{ + int unit = f->unit; + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ + u_short cishort, ts; /* Parsed short value */ + u_int32_t tl, cinetwork, outnet;/* Parsed address values */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ + u_char maxslotindex, cflag; + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPXCPDEBUG((LOG_INFO, "ipxcp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ +/* + * The network number must match. Choose the larger of the two. + */ + case IPX_NETWORK_NUMBER: + IPXCPDEBUG((LOG_INFO, "ipxcp: received Network Number request")); + + /* if we wont negotiate the network number or the length is wrong + then reject the option */ + if ( !ao->neg_nn || cilen != CILEN_NETN ) { + orc = CONFREJ; + break; + } + GETLONG(cinetwork, p); + IPXCPDEBUG((LOG_INFO,"Remote proposed IPX network number is %8Lx",tl)); + + /* If the network numbers match then acknowledge them. */ + if (cinetwork != 0) { + ho->his_network = cinetwork; + ho->neg_nn = 1; + if (wo->our_network == cinetwork) + break; +/* + * If the network number is not given or we don't accept their change or + * the network number is too small then NAK it. + */ + if (! ao->accept_network || cinetwork < wo->our_network) { + DECPTR (sizeof (u_int32_t), p); + PUTLONG (wo->our_network, p); + orc = CONFNAK; + } + break; + } +/* + * The peer sent '0' for the network. Give it ours if we have one. + */ + if (go->our_network != 0) { + DECPTR (sizeof (u_int32_t), p); + PUTLONG (wo->our_network, p); + orc = CONFNAK; +/* + * We don't have one. Reject the value. + */ + } else + orc = CONFREJ; + + break; +/* + * The node number is required + */ + case IPX_NODE_NUMBER: + IPXCPDEBUG((LOG_INFO, "ipxcp: received Node Number request")); + + /* if we wont negotiate the node number or the length is wrong + then reject the option */ + if ( cilen != CILEN_NODEN ) { + orc = CONFREJ; + break; + } + + copy_node (p, ho->his_node); + ho->neg_node = 1; +/* + * If the remote does not have a number and we do then NAK it with the value + * which we have for it. (We never have a default value of zero.) + */ + if (zero_node (ho->his_node)) { + orc = CONFNAK; + copy_node (wo->his_node, p); + INCPTR (sizeof (wo->his_node), p); + break; + } +/* + * If you have given me the expected network node number then I'll accept + * it now. + */ + if (compare_node (wo->his_node, ho->his_node)) { + orc = CONFACK; + ho->neg_node = 1; + INCPTR (sizeof (wo->his_node), p); + break; + } +/* + * If his node number is the same as ours then ask him to try the next + * value. + */ + if (compare_node (ho->his_node, go->our_node)) { + inc_node (ho->his_node); + orc = CONFNAK; + copy_node (ho->his_node, p); + INCPTR (sizeof (wo->his_node), p); + break; + } +/* + * If we don't accept a new value then NAK it. + */ + if (! ao->accept_remote) { + copy_node (wo->his_node, p); + INCPTR (sizeof (wo->his_node), p); + orc = CONFNAK; + break; + } + orc = CONFACK; + ho->neg_node = 1; + INCPTR (sizeof (wo->his_node), p); + break; +/* + * Compression is not desired at this time. It is always rejected. + */ + case IPX_COMPRESSION_PROTOCOL: + IPXCPDEBUG((LOG_INFO, "ipxcp: received Compression Protocol request ")); + orc = CONFREJ; + break; +/* + * The routing protocol is a bitmask of various types. Any combination + * of the values 2 and 4 are permissible. '0' for no routing protocol must + * be specified only once. + */ + case IPX_ROUTER_PROTOCOL: + if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) { + orc = CONFREJ; + break; + } + + GETSHORT (cishort, p); + IPXCPDEBUG((LOG_INFO, + "Remote router protocol number %d", + cishort)); + + if ((cishort == 0 && ho->router != 0) || (ho->router & BIT(0))) { + orc = CONFREJ; + break; + } + + if (cishort != 0 && cishort != 2 && cishort != 4) { + orc = CONFREJ; + break; + } + + if (ho->router & BIT (cishort)) { + orc = CONFREJ; + break; + } + + ho->router |= BIT (cishort); + ho->neg_router = 1; + break; +/* + * The router name is advisorary. Just accept it if it is not too large. + */ + case IPX_ROUTER_NAME: + IPXCPDEBUG((LOG_INFO, "ipxcp: received Router Name request")); + if (cilen >= CILEN_NAME) { + int name_size = cilen - CILEN_NAME; + if (name_size > sizeof (ho->name)) + name_size = sizeof (ho->name) - 1; + memset (ho->name, 0, sizeof (ho->name)); + memcpy (ho->name, p, name_size); + ho->name [name_size] = '\0'; + ho->neg_name = 1; + orc = CONFACK; + break; + } + orc = CONFREJ; + break; +/* + * This is advisorary. + */ + case IPX_COMPLETE: + IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request")); + if (cilen != CILEN_COMPLETE) + orc = CONFREJ; + else { + ho->neg_complete = 1; + orc = CONFACK; + } + break; +/* + * All other entries are not known at this time. + */ + default: + IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request")); + orc = CONFREJ; + break; + } + +endswitch: + IPXCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc))); + + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + orc = CONFREJ; /* Get tough if so */ + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) + BCOPY(cip, ucp, cilen); /* Move it */ + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their address, and they didn't send their address, then we + * send a NAK with a IPX_NODE_NUMBER option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + + if (rc != CONFREJ && !ho->neg_node && + wo->req_nn && !reject_if_disagree) { + u_char *ps; + if (rc == CONFACK) { + rc = CONFNAK; + wo->req_nn = 0; /* don't ask again */ + ucp = inp; /* reset pointer */ + } + + if (zero_node (wo->his_node)) + inc_node (wo->his_node); + + PUTCHAR (IPX_NODE_NUMBER, ucp); + PUTCHAR (CILEN_NODEN, ucp); + copy_node (wo->his_node, ucp); + INCPTR (sizeof (wo->his_node), ucp); + } + + *len = ucp - inp; /* Compute output length */ + IPXCPDEBUG((LOG_INFO, "ipxcp: returning Configure-%s", CODENAME(rc))); + return (rc); /* Return final code */ +} + +/* + * ipxcp_up - IPXCP has come UP. + * + * Configure the IP network interface appropriately and bring it up. + */ + +static void +ipxcp_up(f) + fsm *f; +{ + int unit = f->unit; + + IPXCPDEBUG((LOG_INFO, "ipxcp: up")); + + if (!ho->neg_nn) + ho->his_network = wo->his_network; + + if (!ho->neg_node) + copy_node (wo->his_node, ho->his_node); + + if (!wo->neg_node && !go->neg_node) + copy_node (wo->our_node, go->our_node); + + if (zero_node (go->our_node)) { + IPXCPDEBUG((LOG_ERR, "Could not determine local IPX node address")); + ipxcp_close(f->unit, "Could not determine local IPX node address"); + return; + } + + go->network = go->our_network; + if (ho->his_network != 0 && ho->his_network > go->network) + go->network = ho->his_network; + + if (go->network == 0) { + IPXCPDEBUG((LOG_ERR, "Could not determine network number")); + ipxcp_close (unit, "Could not determine network number"); + return; + } + + /* bring the interface up */ + if (!sifup(unit)) { + IPXCPDEBUG((LOG_WARNING, "sifup failed")); + ipxcp_close(unit, "Interface configuration failed"); + return; + } + + /* set the network number for IPX */ + if (!sipxfaddr(unit, go->network, go->our_node)) { + IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed")); + ipxcp_close(unit, "Interface configuration failed"); + return; + } + + /* + * Execute the ipx-up script, like this: + * /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX + */ + + ipxcp_script (f, "/etc/ppp/ipx-up"); +} + +/* + * ipxcp_down - IPXCP has gone DOWN. + * + * Take the IP network interface down, clear its addresses + * and delete routes through it. + */ + +static void +ipxcp_down(f) + fsm *f; +{ + u_int32_t ournn, network; + + IPXCPDEBUG((LOG_INFO, "ipxcp: down")); + + cipxfaddr (f->unit); + sifdown(f->unit); + ipxcp_script (f, "/etc/ppp/ipx-down"); +} + + +/* + * ipxcp_script - Execute a script with arguments + * interface-name tty-name speed local-IPX remote-IPX networks. + */ +static void +ipxcp_script(f, script) + fsm *f; + char *script; +{ + int unit = f->unit; + char strspeed[32], strlocal[32], strremote[32]; + char strnetwork[32], strpid[32]; + char *argv[14], strproto_lcl[32], strproto_rmt[32]; + + sprintf (strpid, "%d", getpid()); + sprintf (strspeed, "%d", baud_rate); + + strproto_lcl[0] = '\0'; + if (go->neg_router) { + if (go->router & BIT(2)) + strcpy (strproto_lcl, "RIP "); + if (go->router & BIT(4)) + strcpy (strproto_lcl, "NLSP "); + } + + if (strproto_lcl[0] == '\0') + strcpy (strproto_lcl, "NONE "); + + strproto_lcl[strlen (strproto_lcl)-1] = '\0'; + + strproto_rmt[0] = '\0'; + if (ho->neg_router) { + if (ho->router & BIT(2)) + strcpy (strproto_rmt, "RIP "); + if (ho->router & BIT(4)) + strcpy (strproto_rmt, "NLSP "); + } + + if (strproto_rmt[0] == '\0') + strcpy (strproto_rmt, "NONE "); + + strproto_rmt[strlen (strproto_rmt)-1] = '\0'; + + strcpy (strnetwork, ipx_ntoa (go->network)); + + sprintf (strlocal, + "%02X%02X%02X%02X%02X%02X", + NODE(go->our_node)); + + sprintf (strremote, + "%02X%02X%02X%02X%02X%02X", + NODE(ho->his_node)); + + argv[0] = script; + argv[1] = ifname; + argv[2] = devnam; + argv[3] = strspeed; + argv[4] = strnetwork; + argv[5] = strlocal; + argv[6] = strremote; + argv[7] = strproto_lcl; + argv[8] = strproto_rmt; + argv[9] = go->name; + argv[10] = ho->name; + argv[11] = ipparam; + argv[12] = strpid; + argv[13] = NULL; + run_program(script, argv, 0); +} + +/* + * ipxcp_printpkt - print the contents of an IPXCP packet. + */ +static char *ipxcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +static int +ipxcp_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer)(); + void *arg; +{ + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + u_int32_t cilong; + + 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(ipxcp_codenames) / sizeof(char *)) + printer(arg, " %s", ipxcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < CILEN_VOID || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case IPX_NETWORK_NUMBER: + if (olen == CILEN_NETN) { + p += CILEN_VOID; + GETLONG(cilong, p); + printer (arg, "network %s", ipx_ntoa (cilong)); + } + break; + case IPX_NODE_NUMBER: + if (olen == CILEN_NODEN) { + p += CILEN_VOID; + printer (arg, "node "); + while (p < optend) { + GETCHAR(code, p); + printer(arg, "%.2x", code); + } + } + break; + case IPX_COMPRESSION_PROTOCOL: + if (olen == CILEN_COMPRESS) { + p += CILEN_VOID; + GETSHORT (cishort, p); + printer (arg, "compression %d", cishort); + } + break; + case IPX_ROUTER_PROTOCOL: + if (olen == CILEN_PROTOCOL) { + p += CILEN_VOID; + GETSHORT (cishort, p); + printer (arg, "router proto %d", cishort); + } + break; + case IPX_ROUTER_NAME: + if (olen >= CILEN_NAME) { + p += CILEN_VOID; + printer (arg, "router name \""); + while (p < optend) { + GETCHAR(code, p); + if (code >= 0x20 && code < 0x7E) + printer (arg, "%c", code); + else + printer (arg, " \\%.2x", code); + } + printer (arg, "\""); + } + break; + case IPX_COMPLETE: + if (olen == CILEN_COMPLETE) { + p += CILEN_VOID; + printer (arg, "complete"); + } + break; + default: + break; + } + + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* ifdef IPX_CHANGE */ diff --git a/usr.sbin/pppd/ipxcp.h b/usr.sbin/pppd/ipxcp.h new file mode 100644 index 00000000000..6dac3f865e8 --- /dev/null +++ b/usr.sbin/pppd/ipxcp.h @@ -0,0 +1,64 @@ +/* + * 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 1996/07/20 12:02:09 joshd 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; diff --git a/usr.sbin/pppd/lcp.c b/usr.sbin/pppd/lcp.c index dd04e02fde2..a0dfdcd747d 100644 --- a/usr.sbin/pppd/lcp.c +++ b/usr.sbin/pppd/lcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lcp.c,v 1.2 1996/03/25 15:55:46 niklas Exp $ */ +/* $OpenBSD: lcp.c,v 1.3 1996/07/20 12:02:10 joshd Exp $ */ /* * lcp.c - PPP Link Control Protocol. @@ -20,7 +20,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: lcp.c,v 1.2 1996/03/25 15:55:46 niklas Exp $"; +static char rcsid[] = "$OpenBSD: lcp.c,v 1.3 1996/07/20 12:02:10 joshd Exp $"; #endif /* @@ -103,11 +103,34 @@ static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ "LCP" /* String name of protocol */ }; +/* + * Protocol entry points. + * Some of these are called directly. + */ + +static void lcp_init __P((int)); +static void lcp_input __P((int, u_char *, int)); +static void lcp_protrej __P((int)); +static int lcp_printpkt __P((u_char *, int, + void (*) __P((void *, char *, ...)), void *)); + struct protent lcp_protent = { - PPP_LCP, lcp_init, lcp_input, lcp_protrej, - lcp_lowerup, lcp_lowerdown, lcp_open, lcp_close, - lcp_printpkt, NULL, 1, "LCP", NULL, NULL -}; + PPP_LCP, + lcp_init, + lcp_input, + lcp_protrej, + lcp_lowerup, + lcp_lowerdown, + lcp_open, + lcp_close, + lcp_printpkt, + NULL, + 1, + "LCP", + NULL, + NULL, + NULL +}; int lcp_loopbackfail = DEFLOOPBACKFAIL; @@ -127,7 +150,7 @@ int lcp_loopbackfail = DEFLOOPBACKFAIL; /* * lcp_init - Initialize LCP. */ -void +static void lcp_init(unit) int unit; { @@ -203,6 +226,7 @@ lcp_close(unit, reason) { fsm *f = &lcp_fsm[unit]; + phase = PHASE_TERMINATE; if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { /* * This action is not strictly according to the FSM in RFC1548, @@ -257,7 +281,7 @@ lcp_lowerdown(unit) /* * lcp_input - Input LCP packet. */ -void +static void lcp_input(unit, p, len) int unit; u_char *p; @@ -366,7 +390,7 @@ lcp_rprotrej(f, inp, len) * lcp_protrej - A Protocol-Reject was received. */ /*ARGSUSED*/ -void +static void lcp_protrej(unit) int unit; { @@ -411,6 +435,7 @@ lcp_resetci(f) lcp_wantoptions[f->unit].numloops = 0; lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit]; peer_mru[f->unit] = PPP_MRU; + auth_reset(f->unit); } @@ -739,8 +764,11 @@ lcp_nakci(f, p, len) */ if ((go->neg_chap || go->neg_upap) && len >= CILEN_SHORT - && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT) { + && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { cilen = p[1]; + len -= cilen; + no.neg_chap = go->neg_chap; + no.neg_upap = go->neg_upap; INCPTR(2, p); GETSHORT(cishort, p); if (cishort == PPP_PAP && cilen == CILEN_SHORT) { @@ -751,7 +779,7 @@ lcp_nakci(f, p, len) */ if (!go->neg_chap) goto bad; - go->neg_chap = 0; + try.neg_chap = 0; } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { GETCHAR(cichar, p); @@ -762,12 +790,12 @@ lcp_nakci(f, p, len) * asking for CHAP. */ if (cichar != go->chap_mdtype) - go->neg_chap = 0; + try.neg_chap = 0; } else { /* * Stop asking for PAP if we were asking for it. */ - go->neg_upap = 0; + try.neg_upap = 0; } } else { @@ -776,9 +804,9 @@ lcp_nakci(f, p, len) * Stop asking for what we were asking for. */ if (go->neg_chap) - go->neg_chap = 0; + try.neg_chap = 0; else - go->neg_upap = 0; + try.neg_upap = 0; p += cilen - CILEN_SHORT; } } @@ -813,7 +841,11 @@ lcp_nakci(f, p, len) try.magicnumber = magic(); looped_back = 1; ); - + /* + * Peer shouldn't send Nak for protocol compression or + * address/control compression requests; they should send + * a Reject instead. If they send a Nak, treat it as a Reject. + */ NAKCIVOID(CI_PCOMPRESSION, neg_pcompression, try.neg_pcompression = 0; ); @@ -840,7 +872,7 @@ lcp_nakci(f, p, len) while (len > CILEN_VOID) { GETCHAR(citype, p); GETCHAR(cilen, p); - if ((len -= cilen) < 0) + if (cilen < CILEN_VOID || (len -= cilen) < 0) goto bad; next = p + cilen - 2; @@ -1056,7 +1088,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) lcp_options *ho = &lcp_hisoptions[f->unit]; lcp_options *ao = &lcp_allowoptions[f->unit]; u_char *cip, *next; /* Pointer to current and next CIs */ - u_char cilen, citype, cichar;/* Parsed len, type, char value */ + int cilen, citype, cichar;/* Parsed len, type, char value */ u_short cishort; /* Parsed short value */ u_int32_t cilong; /* Parse long value */ int rc = CONFACK; /* Final packet return code */ @@ -1206,7 +1238,11 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) break; } GETCHAR(cichar, p); /* get digest type*/ - if (cichar != ao->chap_mdtype) { + if (cichar != CHAP_DIGEST_MD5 +#ifdef CHAPMS + && cichar != CHAP_MICROSOFT +#endif + ) { orc = CONFNAK; PUTCHAR(CI_AUTHTYPE, nakp); PUTCHAR(CILEN_CHAP, nakp); @@ -1460,13 +1496,13 @@ lcp_finished(f) /* * lcp_printpkt - print the contents of an LCP packet. */ -char *lcp_codenames[] = { +static char *lcp_codenames[] = { "ConfReq", "ConfAck", "ConfNak", "ConfRej", "TermReq", "TermAck", "CodeRej", "ProtRej", "EchoReq", "EchoRep", "DiscReq" }; -int +static int lcp_printpkt(p, plen, printer, arg) u_char *p; int plen; @@ -1477,6 +1513,7 @@ lcp_printpkt(p, plen, printer, arg) u_char *pstart, *optend; u_short cishort; u_int32_t cilong; + int fascii; if (plen < HEADERLEN) return 0; @@ -1582,6 +1619,27 @@ lcp_printpkt(p, plen, printer, arg) printer(arg, ">"); } break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + + case ECHOREQ: + case ECHOREP: + case DISCREQ: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + p += 4; + len -= 4; + } + break; } /* print the rest of the bytes in the packet */ diff --git a/usr.sbin/pppd/lcp.h b/usr.sbin/pppd/lcp.h index 196a15ce10f..e7ad1b3eb19 100644 --- a/usr.sbin/pppd/lcp.h +++ b/usr.sbin/pppd/lcp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: lcp.h,v 1.2 1996/03/25 15:55:47 niklas Exp $ */ +/* $OpenBSD: lcp.h,v 1.3 1996/07/20 12:02:11 joshd Exp $ */ /* * lcp.h - Link Control Protocol definitions. @@ -72,16 +72,11 @@ extern u_int32_t xmit_accm[][8]; #define MINMRU 128 /* No MRUs below this */ #define MAXMRU 16384 /* Normally limit MRU to this */ -void lcp_init __P((int)); void lcp_open __P((int)); void lcp_close __P((int, char *)); void lcp_lowerup __P((int)); void lcp_lowerdown __P((int)); -void lcp_input __P((int, u_char *, int)); -void lcp_protrej __P((int)); -void lcp_sprotrej __P((int, u_char *, int)); -int lcp_printpkt __P((u_char *, int, - void (*) __P((void *, char *, ...)), void *)); +void lcp_sprotrej __P((int, u_char *, int)); /* send protocol reject */ extern struct protent lcp_protent; diff --git a/usr.sbin/pppd/main.c b/usr.sbin/pppd/main.c index f7d307941fd..2b2e9e0daac 100644 --- a/usr.sbin/pppd/main.c +++ b/usr.sbin/pppd/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.8 1996/06/17 07:20:53 deraadt Exp $ */ +/* $OpenBSD: main.c,v 1.9 1996/07/20 12:02:11 joshd Exp $ */ /* * main.c - Point-to-Point Protocol main module @@ -20,7 +20,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: main.c,v 1.8 1996/06/17 07:20:53 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: main.c,v 1.9 1996/07/20 12:02:11 joshd Exp $"; #endif #include <stdio.h> @@ -78,10 +78,15 @@ static pid_t pid; /* Our pid */ static uid_t uid; /* Our real user-id */ int ttyfd = -1; /* Serial port file descriptor */ +mode_t tty_mode = -1; /* Original access permissions to tty */ +int baud_rate; /* Actual bits/second for serial device */ +int hungup; /* terminal has been hung up */ + int phase; /* where the link is at */ int kill_link; int open_ccp_flag; +int redirect_stderr; /* Connector's stderr should go to file */ u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */ u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */ @@ -122,6 +127,10 @@ extern char *getlogin __P((void)); #define O_NONBLOCK O_NDELAY #endif +#ifdef PRIMITIVE_SYSLOG +#define setlogmask(x) +#endif + /* * PPP Data Link Layer "protocol" table. * One entry per supported protocol. @@ -152,14 +161,24 @@ main(argc, argv) struct timeval timo; sigset_t mask; struct protent *protp; + struct stat statbuf; + phase = PHASE_INITIALIZE; p = ttyname(0); if (p) strcpy(devnam, p); strcpy(default_devnam, devnam); + /* Initialize syslog facilities */ +#ifdef PRIMITIVE_SYSLOG + openlog("pppd", LOG_PID); +#else + openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); + setlogmask(LOG_UPTO(LOG_INFO)); +#endif + if (gethostname(hostname, MAXNAMELEN) < 0 ) { - perror("couldn't get hostname"); + syslog(LOG_ERR, "couldn't get hostname: %m"); die(1); } hostname[MAXNAMELEN-1] = 0; @@ -168,18 +187,20 @@ main(argc, argv) /* * Initialize to the standard option set, then parse, in order, - * the system options file, the user's options file, and the command - * line arguments. + * the system options file, the user's options file, + * the tty's options file, and the command line arguments. */ for (i = 0; (protp = protocols[i]) != NULL; ++i) (*protp->init)(0); progname = *argv; - if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) || - !options_from_user() || - !parse_args(argc-1, argv+1) || - !options_for_tty() ) + if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) + || !options_from_user()) + exit(1); + scan_args(argc-1, argv+1); /* look for tty name on command line */ + if (!options_for_tty() + || !parse_args(argc-1, argv+1)) exit(1); if (!ppp_available()) { @@ -207,12 +228,17 @@ main(argc, argv) */ if (!default_device && strcmp(devnam, default_devnam) == 0) default_device = 1; + redirect_stderr = !nodetach || default_device; + /* * Initialize system-dependent stuff and magic number package. */ sys_init(); magic_init(); + if (debug) + setlogmask(LOG_UPTO(LOG_DEBUG)); + /* * Detach ourselves from the terminal, if required, @@ -303,6 +329,13 @@ main(argc, argv) #endif /* + * Apparently we can get a SIGPIPE when we call syslog, if + * syslogd has died and been restarted. Ignoring it seems + * be sufficient. + */ + signal(SIGPIPE, SIG_IGN); + + /* * If we're doing dial-on-demand, set up the interface now. */ if (demand) { @@ -388,6 +421,16 @@ main(argc, argv) hungup = 0; kill_link = 0; + /* + * Do the equivalent of `mesg n' to stop broadcast messages. + */ + if (fstat(ttyfd, &statbuf) < 0 + || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) { + syslog(LOG_WARNING, + "Couldn't restrict write permissions to %s: %m", devnam); + } else + tty_mode = statbuf.st_mode; + /* run connection script */ if (connector && connector[0]) { MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); @@ -467,7 +510,7 @@ main(argc, argv) if (open_ccp_flag) { if (phase == PHASE_NETWORK) { ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ - ccp_open(0); + (*ccp_protent.open)(0); } open_ccp_flag = 0; } @@ -505,7 +548,8 @@ main(argc, argv) } if (!demand) { - if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) + if (pidfilename[0] != 0 + && unlink(pidfilename) < 0 && errno != ENOENT) syslog(LOG_WARNING, "unable to delete pid file: %m"); pidfilename[0] = 0; } @@ -686,6 +730,9 @@ close_tty() restore_tty(ttyfd); + if (tty_mode != (mode_t) -1) + chmod(devnam, tty_mode); + close(ttyfd); ttyfd = -1; } @@ -875,7 +922,11 @@ toggle_debug(sig) int sig; { debug = !debug; - note_debug_level(); + if (debug) { + setlogmask(LOG_UPTO(LOG_DEBUG)); + } else { + setlogmask(LOG_UPTO(LOG_WARNING)); + } } @@ -927,11 +978,33 @@ device_script(program, in, out) if (pid == 0) { sys_close(); - dup2(in, 0); - dup2(out, 1); - errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644); - if (errfd >= 0) - dup2(errfd, 2); + closelog(); + if (in == out) { + if (in != 0) { + dup2(in, 0); + close(in); + } + dup2(0, 1); + } else { + if (out == 0) + out = dup(out); + if (in != 0) { + dup2(in, 0); + close(in); + } + if (out != 1) { + dup2(out, 1); + close(out); + } + } + if (redirect_stderr) { + close(2); + errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644); + if (errfd >= 0 && errfd != 2) { + dup2(errfd, 2); + close(errfd); + } + } setuid(getuid()); setgid(getgid()); execl("/bin/sh", "sh", "-c", program, (char *)0); @@ -964,6 +1037,8 @@ run_program(prog, args, must_exist) int must_exist; { int pid; + char *nullenv[1]; + pid = fork(); if (pid == -1) { @@ -982,6 +1057,7 @@ run_program(prog, args, must_exist) /* Ensure that nothing of our device environment is inherited. */ sys_close(); + closelog(); close (0); close (1); close (2); @@ -1006,7 +1082,9 @@ run_program(prog, args, must_exist) /* SysV recommends a second fork at this point. */ - execv(prog, args); + /* run the program; give it a null environment */ + nullenv[0] = NULL; + execve(prog, args, nullenv); if (must_exist || errno != ENOENT) syslog(LOG_WARNING, "Can't execute %s: %m", prog); _exit(-1); @@ -1103,43 +1181,23 @@ format_packet(p, len, printer, arg) } } -#ifdef __STDC__ -#include <stdarg.h> - static void -pr_log(void *arg, char *fmt, ...) +pr_log __V((void *arg, char *fmt, ...)) { int n; va_list pvar; char buf[256]; +#if __STDC__ va_start(pvar, fmt); - vsprintf(buf, fmt, pvar); - va_end(pvar); - - n = strlen(buf); - if (linep + n + 1 > line + sizeof(line)) { - syslog(LOG_DEBUG, "%s", line); - linep = line; - } - strcpy(linep, buf); - linep += n; -} - -#else /* __STDC__ */ -#include <varargs.h> - -static void -pr_log(arg, fmt, va_alist) -void *arg; -char *fmt; -va_dcl -{ - int n; - va_list pvar; - char buf[256]; - +#else + void *arg; + char *fmt; va_start(pvar); + arg = va_arg(pvar, void *); + fmt = va_arg(pvar, char *); +#endif + vsprintf(buf, fmt, pvar); va_end(pvar); @@ -1151,7 +1209,6 @@ va_dcl strcpy(linep, buf); linep += n; } -#endif /* * print_string - print a readable representation of a string using @@ -1169,11 +1226,27 @@ print_string(p, len, printer, arg) printer(arg, "\""); for (; len > 0; --len) { c = *p++; - if (' ' <= c && c <= '~') + if (' ' <= c && c <= '~') { + if (c == '\\' || c == '"') + printer(arg, "\\"); printer(arg, "%c", c); - else - printer(arg, "\\%.3o", c); + } else { + switch (c) { + case '\n': + printer(arg, "\\n"); + break; + case '\r': + printer(arg, "\\r"); + break; + case '\t': + printer(arg, "\\t"); + break; + default: + printer(arg, "\\%.3o", c); + } + } } + printer(arg, "\""); } @@ -1187,3 +1260,246 @@ novm(msg) syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg); die(1); } + +/* + * fmtmsg - format a message into a buffer. Like sprintf except we + * also specify the length of the output buffer, and we handle + * %r (recursive format), %m (error message) and %I (IP address) formats. + * Doesn't do floating-point formats. + * Returns the number of chars put into buf. + */ +int +fmtmsg __V((char *buf, int buflen, char *fmt, ...)) +{ + va_list args; + int n; + +#if __STDC__ + va_start(args, fmt); +#else + char *buf; + int buflen; + char *fmt; + va_start(args); + buf = va_arg(args, char *); + buflen = va_arg(args, int); + fmt = va_arg(args, char *); +#endif + n = vfmtmsg(buf, buflen, fmt, args); + va_end(args); + return n; +} + +/* + * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args. + */ +#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) + +int +vfmtmsg(char *buf, int buflen, char *fmt, va_list args) +{ + int c, i, n; + int width, prec, fillch; + int base, len, neg, quoted; + unsigned long val; + char *str, *f, *buf0; + unsigned char *p; + va_list a; + char num[32]; + time_t t; + static char hexchars[16] = "0123456789abcdef"; + + buf0 = buf; + --buflen; + while (buflen > 0) { + for (f = fmt; *f != '%' && *f != 0; ++f) + ; + if (f > fmt) { + len = f - fmt; + if (len > buflen) + len = buflen; + memcpy(buf, fmt, len); + buf += len; + buflen -= len; + fmt = f; + } + if (*fmt == 0) + break; + c = *++fmt; + width = prec = 0; + fillch = ' '; + if (c == '0') { + fillch = '0'; + c = *++fmt; + } + if (c == '*') { + width = va_arg(args, int); + c = *++fmt; + } else { + while (isdigit(c)) { + width = width * 10 + c - '0'; + c = *++fmt; + } + } + if (c == '.') { + c = *++fmt; + if (c == '*') { + prec = va_arg(args, int); + c = *++fmt; + } else { + while (isdigit(c)) { + prec = prec * 10 + c - '0'; + c = *++fmt; + } + } + } + str = 0; + base = 0; + neg = 0; + ++fmt; + switch (c) { + case 'd': + i = va_arg(args, int); + if (i < 0) { + neg = 1; + val = -i; + } else + val = i; + base = 10; + break; + case 'o': + val = va_arg(args, unsigned int); + base = 8; + break; + case 'x': + val = va_arg(args, unsigned int); + base = 16; + break; + case 'p': + val = (unsigned long) va_arg(args, void *); + base = 16; + neg = 2; + break; + case 's': + str = va_arg(args, char *); + break; + case 'c': + num[0] = va_arg(args, int); + num[1] = 0; + str = num; + break; + case 'm': + str = strerror(errno); + break; + case 'I': + str = ip_ntoa(va_arg(args, u_int32_t)); + break; + case 'r': + f = va_arg(args, char *); + a = va_arg(args, va_list); + n = vfmtmsg(buf, buflen + 1, f, a); + buf += n; + buflen -= n; + continue; + case 't': + time(&t); + str = ctime(&t); + str += 4; /* chop off the day name */ + str[15] = 0; /* chop off year and newline */ + break; + case 'v': /* "visible" string */ + case 'q': /* quoted string */ + quoted = c == 'q'; + p = va_arg(args, unsigned char *); + if (fillch == '0' && prec > 0) { + n = prec; + } else { + n = strlen((char *)p); + if (prec > 0 && prec < n) + n = prec; + } + while (n > 0 && buflen > 0) { + c = *p++; + --n; + if (!quoted && c >= 0x80) { + OUTCHAR('M'); + OUTCHAR('-'); + c -= 0x80; + } + if (quoted && (c == '"' || c == '\\')) + OUTCHAR('\\'); + if (c < 0x20 || 0x7f <= c && c < 0xa0) { + if (quoted) { + OUTCHAR('\\'); + switch (c) { + case '\t': OUTCHAR('t'); break; + case '\n': OUTCHAR('n'); break; + case '\b': OUTCHAR('b'); break; + case '\f': OUTCHAR('f'); break; + default: + OUTCHAR('x'); + OUTCHAR(hexchars[c >> 4]); + OUTCHAR(hexchars[c & 0xf]); + } + } else { + if (c == '\t') + OUTCHAR(c); + else { + OUTCHAR('^'); + OUTCHAR(c ^ 0x40); + } + } + } else + OUTCHAR(c); + } + continue; + default: + *buf++ = '%'; + if (c != '%') + --fmt; /* so %z outputs %z etc. */ + --buflen; + continue; + } + if (base != 0) { + str = num + sizeof(num); + *--str = 0; + while (str > num + neg) { + *--str = hexchars[val % base]; + val = val / base; + if (--prec <= 0 && val == 0) + break; + } + switch (neg) { + case 1: + *--str = '-'; + break; + case 2: + *--str = 'x'; + *--str = '0'; + break; + } + len = num + sizeof(num) - 1 - str; + } else { + len = strlen(str); + if (prec > 0 && len > prec) + len = prec; + } + if (width > 0) { + if (width > buflen) + width = buflen; + if ((n = width - len) > 0) { + buflen -= n; + for (; n > 0; --n) + *buf++ = fillch; + } + } + if (len > buflen) + len = buflen; + memcpy(buf, str, len); + buf += len; + buflen -= len; + } + *buf = 0; + return buf - buf0; +} + diff --git a/usr.sbin/pppd/md4.c b/usr.sbin/pppd/md4.c new file mode 100644 index 00000000000..7d55856db82 --- /dev/null +++ b/usr.sbin/pppd/md4.c @@ -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 --git a/usr.sbin/pppd/md4.h b/usr.sbin/pppd/md4.h new file mode 100644 index 00000000000..af7af073b24 --- /dev/null +++ b/usr.sbin/pppd/md4.h @@ -0,0 +1,52 @@ + +/* +** ******************************************************************** +** 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)***********************************/ diff --git a/usr.sbin/pppd/options.c b/usr.sbin/pppd/options.c index 6ed99da6de8..a47eedd33ec 100644 --- a/usr.sbin/pppd/options.c +++ b/usr.sbin/pppd/options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options.c,v 1.3 1996/04/21 23:41:23 deraadt Exp $ */ +/* $OpenBSD: options.c,v 1.4 1996/07/20 12:02:13 joshd Exp $ */ /* * options.c - handles option processing for PPP. @@ -20,7 +20,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: options.c,v 1.3 1996/04/21 23:41:23 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: options.c,v 1.4 1996/07/20 12:02:13 joshd Exp $"; #endif #include <ctype.h> @@ -104,11 +104,14 @@ int idle_time_limit = 0; /* Disconnect if idle for this many seconds */ int holdoff = 30; /* # seconds to pause before reconnecting */ struct bpf_program pass_filter;/* Filter program for packets to pass */ struct bpf_program active_filter; /* Filter program for link-active pkts */ +int refuse_pap = 0; /* Set to say we won't do PAP */ +int refuse_chap = 0; /* Set to say we won't do CHAP */ + /* * Prototypes */ -static int setdevname __P((char *)); +static int setdevname __P((char *, int)); static int setipaddr __P((char *)); static int setdebug __P((void)); static int setkdebug __P((char **)); @@ -120,7 +123,9 @@ static int setnovjccomp __P((void)); static int setvjslots __P((char **)); static int reqpap __P((void)); static int nopap __P((void)); +#ifdef OLD_OPTIONS static int setupapfile __P((char **)); +#endif static int nochap __P((void)); static int reqchap __P((void)); static int setspeed __P((char *)); @@ -214,7 +219,9 @@ static int setdnsaddr __P((char **)); #endif static int number_option __P((char *, u_int32_t *, int)); +static int int_option __P((char *, int *)); static int readable __P((int fd)); +static void option_error __P((char *fmt, ...)); void usage(); @@ -226,23 +233,40 @@ static struct cmd { int num_args; int (*cmd_func)(); } cmds[] = { - {"-all", 0, noopt}, /* Don't request/allow any options */ + {"-all", 0, noopt}, /* Don't request/allow any options (useless) */ + {"noaccomp", 0, noaccomp}, /* Disable Address/Control compression */ {"-ac", 0, noaccomp}, /* Disable Address/Control compress */ + {"default-asyncmap", 0, noasyncmap}, /* Disable asyncmap negoatiation */ {"-am", 0, noasyncmap}, /* Disable asyncmap negotiation */ {"-as", 1, setasyncmap}, /* set the desired async map */ {"-d", 0, setdebug}, /* Increase debugging level */ + {"nodetach", 0, setnodetach}, /* Don't detach from controlling tty */ {"-detach", 0, setnodetach}, /* don't fork */ + {"noip", 0, noip}, /* Disable IP and IPCP */ {"-ip", 0, noip}, /* Disable IP and IPCP */ + {"nomagic", 0, nomagicnumber}, /* Disable magic number negotiation */ {"-mn", 0, nomagicnumber}, /* Disable magic number negotiation */ + {"default-mru", 0, nomru}, /* Disable MRU negotiation */ {"-mru", 0, nomru}, /* Disable mru negotiation */ {"-p", 0, setpassive}, /* Set passive mode */ + {"nopcomp", 0, nopcomp}, /* Disable protocol field compression */ +#ifdef OLD_OPTIONS {"-pc", 0, nopcomp}, /* Disable protocol field compress */ +#endif + {"require-pap", 0, reqpap}, /* Require PAP authentication from peer */ +#ifdef OLD_OPTIONS {"+ua", 1, setupapfile}, /* Get PAP user and password from file */ +#endif {"+pap", 0, reqpap}, /* Require PAP auth from peer */ + {"refuse-pap", 0, nopap}, /* Don't agree to auth to peer with PAP */ {"-pap", 0, nopap}, /* Don't allow UPAP authentication with peer */ + {"require-chap", 0, reqchap}, /* Require CHAP authentication from peer */ {"+chap", 0, reqchap}, /* Require CHAP authentication from peer */ + {"refuse-chap", 0, nochap}, /* Don't agree to auth to peer with CHAP */ {"-chap", 0, nochap}, /* Don't allow CHAP authentication with peer */ + {"novj", 0, setnovj}, /* Disable VJ compression */ {"-vj", 0, setnovj}, /* disable VJ compression */ + {"novjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */ {"-vjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */ {"vj-max-slots", 1, setvjslots}, /* Set maximum VJ header slots */ {"asyncmap", 1, setasyncmap}, /* set the desired async map */ @@ -252,6 +276,7 @@ static struct cmd { {"welcome", 1, setwelcomer},/* Script to welcome client */ {"maxconnect", 1, setmaxconnect}, /* specify a maximum connect time */ {"crtscts", 0, setcrtscts}, /* set h/w flow control */ + {"nocrtscts", 0, setnocrtscts}, /* clear h/w flow control */ {"-crtscts", 0, setnocrtscts}, /* clear h/w flow control */ {"xonxoff", 0, setxonxoff}, /* set s/w flow control */ {"debug", 0, setdebug}, /* Increase debugging level */ @@ -272,8 +297,10 @@ static struct cmd { {"auth", 0, setauth}, /* Require authentication from peer */ {"file", 1, readfile}, /* Take options from a file */ {"defaultroute", 0, setdefaultroute}, /* Add default route */ + {"nodefaultroute", 0, setnodefaultroute}, /* disable defaultroute option */ {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */ {"proxyarp", 0, setproxyarp}, /* Add proxy ARP entry */ + {"noproxyarp", 0, setnoproxyarp}, /* disable proxyarp option */ {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */ {"persist", 0, setpersist}, /* Keep on reopening connection after close */ {"demand", 0, setdemand}, /* Dial on demand */ @@ -297,12 +324,16 @@ static struct cmd { {"chap-interval", 1, setchapintv}, /* Set interval for rechallenge */ {"ipcp-accept-local", 0, setipcpaccl}, /* Accept peer's address for us */ {"ipcp-accept-remote", 0, setipcpaccr}, /* Accept peer's address for it */ + {"noccp", 0, noccp}, /* Disable CCP negotiation */ {"-ccp", 0, noccp}, /* Disable CCP negotiation */ {"bsdcomp", 1, setbsdcomp}, /* request BSD-Compress */ + {"nobsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */ {"-bsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */ {"deflate", 1, setdeflate}, /* request Deflate compression */ + {"nodeflate", 0, setnodeflate}, /* don't allow Deflate compression */ {"-deflate", 0, setnodeflate}, /* don't allow Deflate compression */ {"predictor1", 0, setpred1comp}, /* request Predictor-1 */ + {"nopredictor1", 0, setnopred1comp},/* don't allow Predictor-1 */ {"-predictor1", 0, setnopred1comp}, /* don't allow Predictor-1 */ {"ipparam", 1, setipparam}, /* set ip script parameter */ {"papcrypt", 0, setpapcrypt}, /* PAP passwords encrypted */ @@ -326,6 +357,8 @@ static struct cmd { #if 0 {"ipx-compression", 1, setipxcompression}, /* IPX compression number */ #endif + {"ipx", 0, setipxproto}, /* Enable IPXCP (and IPX) */ + {"noipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */ {"+ipx", 0, setipxproto}, /* Enable IPXCP (and IPX) */ {"-ipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */ #endif /* IPX_CHANGE */ @@ -348,7 +381,7 @@ static struct cmd { static char *usage_string = "\ pppd version %s patch level %d%s\n\ -Usage: %s [ arguments ], where arguments are:\n\ +Usage: %s [ options ], where options are:\n\ <device> Communicate over the named device\n\ <speed> Set the baud rate to <speed>\n\ <loc>:<rem> Set the local and/or remote interface IP\n\ @@ -365,6 +398,8 @@ Usage: %s [ arguments ], where arguments are:\n\ See pppd(8) for more options.\n\ "; +static char *current_option; /* the name of the option being parsed */ + /* * parse_args - parse a string of arguments, from the command @@ -392,9 +427,10 @@ parse_args(argc, argv) if (cmdp->cmd_name != NULL) { if (argc < cmdp->num_args) { - fprintf(stderr, "Too few parameters for command %s\n", arg); + option_error("too few parameters for option %s", arg); return 0; } + current_option = arg; if (!(*cmdp->cmd_func)(argv)) return 0; argc -= cmdp->num_args; @@ -404,10 +440,10 @@ parse_args(argc, argv) /* * Maybe a tty name, speed or IP address? */ - if ((ret = setdevname(arg)) == 0 + if ((ret = setdevname(arg, 0)) == 0 && (ret = setspeed(arg)) == 0 && (ret = setipaddr(arg)) == 0) { - fprintf(stderr, "%s: unrecognized command\n", arg); + option_error("unrecognized option '%s'", arg); usage(); return 0; } @@ -419,11 +455,45 @@ parse_args(argc, argv) } /* + * scan_args - scan the command line arguments to get the tty name, + * if specified. + */ +void +scan_args(argc, argv) + int argc; + char **argv; +{ + char *arg; + struct cmd *cmdp; + + while (argc > 0) { + arg = *argv++; + --argc; + + /* Skip options and their arguments */ + for (cmdp = cmds; cmdp->cmd_name; cmdp++) + if (!strcmp(arg, cmdp->cmd_name)) + break; + + if (cmdp->cmd_name != NULL) { + argc -= cmdp->num_args; + argv += cmdp->num_args; + continue; + } + + /* Check if it's a tty name and copy it if so */ + (void) setdevname(arg, 1); + } +} + + +/* * usage - print out a message telling how to use the program. */ void usage() { + if (phase == PHASE_INITIALIZE) fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION, progname); } @@ -448,11 +518,11 @@ options_from_file(filename, must_exist, check_prot) if ((f = fopen(filename, "r")) == NULL) { if (!must_exist && errno == ENOENT) return 1; - perror(filename); + option_error("Can't open options file %s: %m", filename); return 0; } if (check_prot && !readable(fileno(f))) { - fprintf(stderr, "%s: access denied\n", filename); + option_error("Can't open options file %s: access denied", filename); fclose(f); return 0; } @@ -468,14 +538,15 @@ options_from_file(filename, must_exist, check_prot) if (cmdp->cmd_name != NULL) { for (i = 0; i < cmdp->num_args; ++i) { if (!getword(f, args[i], &newline, filename)) { - fprintf(stderr, - "In file %s: too few parameters for command %s\n", + option_error( + "In file %s: too few parameters for option '%s'", filename, cmd); fclose(f); return 0; } argv[i] = args[i]; } + current_option = cmd; if (!(*cmdp->cmd_func)(argv)) { fclose(f); return 0; @@ -485,10 +556,10 @@ options_from_file(filename, must_exist, check_prot) /* * Maybe a tty name, speed or IP address? */ - if ((ret = setdevname(cmd)) == 0 + if ((ret = setdevname(cmd, 0)) == 0 && (ret = setspeed(cmd)) == 0 && (ret = setipaddr(cmd)) == 0) { - fprintf(stderr, "In file %s: unrecognized command %s\n", + option_error("In file %s: unrecognized option '%s'", filename, cmd); fclose(f); return 0; @@ -555,6 +626,33 @@ options_for_tty() } /* + * option_error - print a message about an error in an option. + * The message is logged, and also sent to + * stderr if phase == PHASE_INITIALIZE. + */ +void +option_error __V((char *fmt, ...)) +{ + va_list args; + int n; + char buf[256]; + +#if __STDC__ + va_start(args, fmt); +#else + char *fmt; + va_start(args); + fmt = va_arg(args, char *); +#endif + vfmtmsg(buf, sizeof(buf), fmt, args); + va_end(args); + if (phase == PHASE_INITIALIZE) + fprintf(stderr, "%s: %s\n", progname, buf); + syslog(LOG_ERR, "%s", buf); +} + + +/* * readable - check if a file is readable by the real user. */ static int @@ -801,7 +899,7 @@ getword(f, word, newlinep, filename) if (ferror(f)) { if (errno == 0) errno = EIO; - perror(filename); + option_error("Error reading %s: %m", filename); die(1); } /* @@ -816,8 +914,8 @@ getword(f, word, newlinep, filename) * Warn if the word was too long, and append a terminating null. */ if (len >= MAXWORDLEN) { - fprintf(stderr, "%s: warning: word in file %s too long (%.20s...)\n", - progname, filename, word); + option_error("warning: word in file %s too long (%.20s...)", + filename, word); len = MAXWORDLEN - 1; } word[len] = 0; @@ -841,7 +939,8 @@ number_option(str, valp, base) *valp = strtoul(str, &ptr, base); if (ptr == str) { - fprintf(stderr, "%s: invalid number: %s\n", progname, str); + option_error("invalid numeric parameter '%s' for %s option", + str, current_option); return 0; } return 1; @@ -1008,7 +1107,7 @@ setmtu(argv) if (!number_option(*argv, &mtu, 0)) return 0; if (mtu < MINMRU || mtu > MAXMRU) { - fprintf(stderr, "mtu option value of %ld is too %s\n", mtu, + option_error("mtu option value of %u is too %s", mtu, (mtu < MINMRU? "small": "large")); return 0; } @@ -1059,7 +1158,7 @@ setsilent() static int nopap() { - lcp_allowoptions[0].neg_upap = 0; + refuse_pap = 1; return (1); } @@ -1076,6 +1175,7 @@ reqpap() } +#if OLD_OPTIONS /* * setupapfile - specifies UPAP info for authenticating with peer. */ @@ -1094,7 +1194,7 @@ setupapfile(argv) return 0; } if (!readable(fileno(ufile))) { - fprintf(stderr, "%s: access denied\n", *argv); + option_error("unable to open user login data file %s", *argv); return 0; } check_access(ufile, *argv); @@ -1102,7 +1202,7 @@ setupapfile(argv) /* get username */ if (fgets(user, MAXNAMELEN - 1, ufile) == NULL || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ - fprintf(stderr, "Unable to read user login data file %s.\n", *argv); + option_error("%s: access denied", *argv); return 0; } fclose(ufile); @@ -1117,6 +1217,7 @@ setupapfile(argv) return (1); } +#endif /* @@ -1125,7 +1226,7 @@ setupapfile(argv) static int nochap() { - lcp_allowoptions[0].neg_chap = 0; + refuse_chap = 1; return (1); } @@ -1178,7 +1279,7 @@ setvjslots(argv) if (!int_option(*argv, &value)) return 0; if (value < 2 || value > 16) { - fprintf(stderr, "pppd: vj-max-slots value must be between 2 and 16\n"); + option_error("vj-max-slots value must be between 2 and 16"); return 0; } ipcp_wantoptions [0].maxslotindex = @@ -1241,7 +1342,7 @@ setmaxconnect(argv) if (!int_option(*argv, &value)) return 0; if (value < 0) { - fprintf(stderr, "pppd: maxconnect time must be positive\n"); + option_error("maxconnect time must be positive"); return 0; } maxconnect = value; @@ -1298,12 +1399,13 @@ setescape(argv) while (*p) { n = strtol(p, &endp, 16); if (p == endp) { - fprintf(stderr, "%s: invalid hex number: %s\n", progname, p); + option_error("escape parameter contains invalid hex number '%s'", + p); return 0; } p = endp; if (n < 0 || 0x20 <= n && n <= 0x3F || n == 0x5E || n > 0xFF) { - fprintf(stderr, "%s: can't escape character 0x%x\n", progname, n); + option_error("can't escape character 0x%x", n); ret = 0; } else xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); @@ -1336,12 +1438,16 @@ setspeed(arg) * setdevname - Set the device name. */ static int -setdevname(cp) +setdevname(cp, quiet) char *cp; + int quiet; { struct stat statbuf; char dev[MAXPATHLEN]; - + + if (*cp == 0) + return 0; + if (strncmp("/dev/", cp, 5) != 0) { strcpy(dev, "/dev/"); strncat(dev, cp, MAXPATHLEN - 5); @@ -1353,9 +1459,9 @@ setdevname(cp) * Check if there is a device by this name. */ if (stat(cp, &statbuf) < 0) { - if (errno == ENOENT) + if (errno == ENOENT || quiet) return 0; - syslog(LOG_ERR, cp); + option_error("Couldn't stat %s: %m", cp); return -1; } @@ -1392,7 +1498,7 @@ setipaddr(arg) *colon = '\0'; if ((local = inet_addr(arg)) == -1) { if ((hp = gethostbyname(arg)) == NULL) { - fprintf(stderr, "unknown host: %s\n", arg); + option_error("unknown host: %s", arg); return -1; } else { local = *(u_int32_t *)hp->h_addr; @@ -1403,7 +1509,7 @@ setipaddr(arg) } } if (bad_ip_adrs(local)) { - fprintf(stderr, "bad local IP address %s\n", ip_ntoa(local)); + option_error("bad local IP address %s", ip_ntoa(local)); return -1; } if (local != 0) @@ -1417,7 +1523,7 @@ setipaddr(arg) if (*++colon != '\0') { if ((remote = inet_addr(colon)) == -1) { if ((hp = gethostbyname(colon)) == NULL) { - fprintf(stderr, "unknown host: %s\n", colon); + option_error("unknown host: %s", colon); return -1; } else { remote = *(u_int32_t *)hp->h_addr; @@ -1428,7 +1534,7 @@ setipaddr(arg) } } if (bad_ip_adrs(remote)) { - fprintf(stderr, "bad remote IP address %s\n", ip_ntoa(remote)); + option_error("bad remote IP address %s", ip_ntoa(remote)); return -1; } if (remote != 0) @@ -1482,7 +1588,7 @@ setnetmask(argv) u_int32_t mask; if ((mask = inet_addr(*argv)) == -1 || (netmask & ~mask) != 0) { - fprintf(stderr, "Invalid netmask %s\n", *argv); + option_error("invalid netmask value '%s'", *argv); return 0; } @@ -1596,7 +1702,7 @@ static int setdefaultroute() { if (!ipcp_allowoptions[0].default_route) { - fprintf(stderr, "%s: defaultroute option is disabled\n", progname); + option_error("defaultroute option is disabled"); return 0; } ipcp_wantoptions[0].default_route = 1; @@ -1615,7 +1721,7 @@ static int setproxyarp() { if (!ipcp_allowoptions[0].proxy_arp) { - fprintf(stderr, "%s: proxyarp option is disabled\n", progname); + option_error("proxyarp option is disabled"); return 0; } ipcp_wantoptions[0].proxy_arp = 1; @@ -1784,14 +1890,13 @@ setbsdcomp(argv) abits = strtol(str, &endp, 0); } if (*endp != 0 || endp == str) { - fprintf(stderr, "%s: invalid argument format for bsdcomp option\n", - progname); + option_error("invalid parameter '%s' for bsdcomp option", *argv); return 0; } if (rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS) || abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS)) { - fprintf(stderr, "%s: bsdcomp option values must be 0 or %d .. %d\n", - progname, BSD_MIN_BITS, BSD_MAX_BITS); + option_error("bsdcomp option values must be 0 or %d .. %d", + BSD_MIN_BITS, BSD_MAX_BITS); return 0; } if (rbits > 0) { @@ -1829,15 +1934,14 @@ setdeflate(argv) abits = strtol(str, &endp, 0); } if (*endp != 0 || endp == str) { - fprintf(stderr, "%s: invalid argument format for deflate option\n", - progname); + option_error("invalid parameter '%s' for deflate option", *argv); return 0; } if (rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE) || abits != 0 && (abits < DEFLATE_MIN_SIZE || abits > DEFLATE_MAX_SIZE)) { - fprintf(stderr, "%s: deflate option values must be 0 or %d .. %d\n", - progname, DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); + option_error("deflate option values must be 0 or %d .. %d", + DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); return 0; } if (rbits > 0) { @@ -1958,16 +2062,12 @@ setipxname (argv) while (*src) { ch = *src++; if (! isalnum (ch) && ch != '_') { - fprintf (stderr, - "%s: IPX router name must be alphanumeric or _\n", - progname); + option_error("IPX router name must be alphanumeric or _"); return 0; } if (count >= sizeof (ipxcp_wantoptions[0].name)) { - fprintf (stderr, - "%s: IPX router name is limited to %d characters\n", - progname, + option_error("IPX router name is limited to %d characters", sizeof (ipxcp_wantoptions[0].name) - 1); return 0; } @@ -2079,22 +2179,21 @@ setipxnode(argv) return 1; } - fprintf(stderr, "%s: invalid argument for ipx-node option\n", - progname); + option_error("invalid parameter '%s' for ipx-node option", *argv); return 0; } static int setipxproto() { - ipx_enabled = 1; /* Enable IPXCP and IPX protocol */ + ipxcp_protent.enabled_flag = 1; return 1; } static int resetipxproto() { - ipx_enabled = 0; /* Disable IPXCP and IPX protocol */ + ipxcp_protent.enabled_flag = 0; return 1; } #endif /* IPX_CHANGE */ @@ -2114,7 +2213,8 @@ setdnsaddr(argv) dns = inet_addr(*argv); if (dns == -1) { if ((hp = gethostbyname(*argv)) == NULL) { - fprintf(stderr, "Invalid DNS Address %s\n", *argv); + option_error("invalid address parameter '%s' for ms-dns option", + *argv); return 0; } dns = *(u_int32_t *)hp->h_addr; diff --git a/usr.sbin/pppd/patchlevel.h b/usr.sbin/pppd/patchlevel.h index 4855a1f2bd4..be9ce8cac2f 100644 --- a/usr.sbin/pppd/patchlevel.h +++ b/usr.sbin/pppd/patchlevel.h @@ -1,7 +1,7 @@ -/* $OpenBSD: patchlevel.h,v 1.2 1996/03/25 15:55:52 niklas Exp $ */ +/* $OpenBSD: patchlevel.h,v 1.3 1996/07/20 12:02:13 joshd Exp $ */ #define PATCHLEVEL 0 #define VERSION "2.3" -#define IMPLEMENTATION "alpha2" -#define DATE "6 March 96" +#define IMPLEMENTATION "beta1" +#define DATE "24 May 96" diff --git a/usr.sbin/pppd/pathnames.h b/usr.sbin/pppd/pathnames.h index 152ff75b110..823076e9881 100644 --- a/usr.sbin/pppd/pathnames.h +++ b/usr.sbin/pppd/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.2 1996/03/25 15:55:53 niklas Exp $ */ +/* $OpenBSD: pathnames.h,v 1.3 1996/07/20 12:02:13 joshd Exp $ */ /* * define path names @@ -17,6 +17,8 @@ #define _PATH_SYSOPTIONS "/etc/ppp/options" #define _PATH_IPUP "/etc/ppp/ip-up" #define _PATH_IPDOWN "/etc/ppp/ip-down" +#define _PATH_AUTHUP "/etc/ppp/auth-up" +#define _PATH_AUTHDOWN "/etc/ppp/auth-down" #define _PATH_TTYOPT "/etc/ppp/options." #define _PATH_CONNERRS "/etc/ppp/connect-errors" #define _PATH_USEROPT ".ppprc" diff --git a/usr.sbin/pppd/pppd.h b/usr.sbin/pppd/pppd.h index 33061b389ba..61dde417eb0 100644 --- a/usr.sbin/pppd/pppd.h +++ b/usr.sbin/pppd/pppd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pppd.h,v 1.2 1996/03/25 15:55:55 niklas Exp $ */ +/* $OpenBSD: pppd.h,v 1.3 1996/07/20 12:02:14 joshd Exp $ */ /* * pppd.h - PPP daemon global declarations. @@ -33,6 +33,14 @@ #include <net/ppp_defs.h> #include <net/bpf.h> +#if __STDC__ +#include <stdarg.h> +#define __V(x) x +#else +#include <varargs.h> +#define __V(x) (va_alist) va_dcl +#endif + #define NUM_PPP 1 /* One PPP interface supported (per process) */ /* @@ -57,6 +65,8 @@ extern u_char outpacket_buf[]; /* Buffer for outgoing packets */ extern int phase; /* Current state of link - see values below */ extern int baud_rate; /* Current link speed in bits/sec */ extern char *progname; /* Name of this program */ +extern int redirect_stderr; /* Connector's stderr should go to file */ +extern char peer_authname[]; /* Authenticated name of peer */ /* * Variables set by command-line options. @@ -95,17 +105,21 @@ extern int idle_time_limit;/* Shut down link if idle for this long */ extern int holdoff; /* Dead time before restarting */ extern struct bpf_program pass_filter; /* Filter for pkts to pass */ extern struct bpf_program active_filter; /* Filter for link-active pkts */ +extern int refuse_pap; /* Don't wanna auth. ourselves with PAP */ +extern int refuse_chap; /* Don't wanna auth. ourselves with CHAP */ + /* * Values for phase. */ #define PHASE_DEAD 0 -#define PHASE_DORMANT 1 -#define PHASE_ESTABLISH 2 -#define PHASE_AUTHENTICATE 3 -#define PHASE_NETWORK 4 -#define PHASE_TERMINATE 5 -#define PHASE_HOLDOFF 6 +#define PHASE_INITIALIZE 1 +#define PHASE_DORMANT 2 +#define PHASE_ESTABLISH 3 +#define PHASE_AUTHENTICATE 4 +#define PHASE_NETWORK 5 +#define PHASE_TERMINATE 6 +#define PHASE_HOLDOFF 7 /* * The following struct gives the addresses of procedures to call @@ -113,19 +127,34 @@ extern struct bpf_program active_filter; /* Filter for link-active pkts */ */ struct protent { u_short protocol; /* PPP protocol number */ - void (*init)(); /* Initialization procedure */ - void (*input)(); /* Process a received packet */ - void (*protrej)(); /* Process a received protocol-reject */ - void (*lowerup)(); /* Lower layer has come up */ - void (*lowerdown)(); /* Lower layer has gone down */ - void (*open)(); /* Open the protocol */ - void (*close)(); /* Close the protocol */ - int (*printpkt)(); /* Print a packet in readable form */ - void (*datainput)(); /* Process a received data packet */ + /* 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 */ - void (*check_options)(); /* Check requested options, assign dflts */ - int (*demand_conf)(); /* Configure interface for demand-dial */ + /* 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 */ @@ -153,6 +182,9 @@ void log_packet __P((u_char *, int, char *)); /* Format a packet and log it with syslog */ void print_string __P((char *, int, void (*) (void *, char *, ...), void *)); /* Format a string for output */ +int fmtmsg __P((char *, int, char *, ...)); /* sprintf++ */ +int vfmtmsg __P((char *, int, char *, va_list)); /* vsprintf++ */ + /* Procedures exported from auth.c */ void link_required __P((int)); /* we are starting to use the link */ @@ -164,7 +196,7 @@ void np_down __P((int, int)); /* a network protocol has gone down */ void np_finished __P((int, int)); /* a network protocol no longer needs link */ void auth_peer_fail __P((int, int)); /* peer failed to authenticate itself */ -void auth_peer_success __P((int, int)); +void auth_peer_success __P((int, int, char *, int)); /* peer successfully authenticated itself */ void auth_withpeer_fail __P((int, int)); /* we failed to authenticate ourselves */ @@ -172,6 +204,8 @@ void auth_withpeer_success __P((int, int)); /* we successfully authenticated ourselves */ void auth_check_options __P((void)); /* check authentication options supplied */ +void auth_reset __P((int)); /* check what secrets we have */ + 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)); @@ -263,6 +297,9 @@ int options_from_file __P((char *filename, int must_exist, int check_prot)); /* Parse options from an options file */ int options_from_user __P((void)); /* Parse options from user's .ppprc */ int options_for_tty __P((void)); /* Parse options from /etc/ppp/options.tty */ +void scan_args __P((int argc, char **argv)); + /* Look for tty name in command-line args */ + int getword __P((FILE *f, char *word, int *newlinep, char *filename)); /* Read a word from a file */ diff --git a/usr.sbin/pppd/upap.c b/usr.sbin/pppd/upap.c index ac6725fd86b..5764f86022b 100644 --- a/usr.sbin/pppd/upap.c +++ b/usr.sbin/pppd/upap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: upap.c,v 1.2 1996/03/25 15:55:58 niklas Exp $ */ +/* $OpenBSD: upap.c,v 1.3 1996/07/20 12:02:14 joshd Exp $ */ /* * upap.c - User/Password Authentication Protocol. @@ -20,7 +20,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: upap.c,v 1.2 1996/03/25 15:55:58 niklas Exp $"; +static char rcsid[] = "$OpenBSD: upap.c,v 1.3 1996/07/20 12:02:14 joshd Exp $"; #endif /* @@ -36,10 +36,34 @@ static char rcsid[] = "$OpenBSD: upap.c,v 1.2 1996/03/25 15:55:58 niklas Exp $"; #include "pppd.h" #include "upap.h" +/* + * 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 + 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 */ @@ -56,7 +80,7 @@ static void upap_sresp __P((upap_state *, int, int, char *, int)); /* * upap_init - Initialize a UPAP unit. */ -void +static void upap_init(unit) int unit; { @@ -176,7 +200,7 @@ upap_reqtimeout(arg) * * Start authenticating if pending. */ -void +static void upap_lowerup(unit) int unit; { @@ -203,7 +227,7 @@ upap_lowerup(unit) * * Cancel all timeouts. */ -void +static void upap_lowerdown(unit) int unit; { @@ -224,7 +248,7 @@ upap_lowerdown(unit) * * This shouldn't happen. In any case, pretend lower layer went down. */ -void +static void upap_protrej(unit) int unit; { @@ -245,7 +269,7 @@ upap_protrej(unit) /* * upap_input - Input UPAP packet. */ -void +static void upap_input(unit, inpacket, l) int unit; u_char *inpacket; @@ -362,11 +386,12 @@ upap_rauthreq(u, inp, id, len) retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen); + BZERO(rpasswd, rpasswdlen); upap_sresp(u, retcode, id, msg, msglen); if (retcode == UPAP_AUTHACK) { u->us_serverstate = UPAPSS_OPEN; - auth_peer_success(u->us_unit, PPP_PAP); + auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen); } else { u->us_serverstate = UPAPSS_BADAUTH; auth_peer_fail(u->us_unit, PPP_PAP); @@ -521,11 +546,11 @@ upap_sresp(u, code, id, msg, msglen) /* * upap_printpkt - print the contents of a PAP packet. */ -char *upap_codenames[] = { +static char *upap_codenames[] = { "AuthReq", "AuthAck", "AuthNak" }; -int +static int upap_printpkt(p, plen, printer, arg) u_char *p; int plen; diff --git a/usr.sbin/pppd/upap.h b/usr.sbin/pppd/upap.h index 30c1a676b58..d38b74bf145 100644 --- a/usr.sbin/pppd/upap.h +++ b/usr.sbin/pppd/upap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: upap.h,v 1.2 1996/03/25 15:55:59 niklas Exp $ */ +/* $OpenBSD: upap.h,v 1.3 1996/07/20 12:02:15 joshd Exp $ */ /* * upap.h - User/Password Authentication Protocol definitions. @@ -82,14 +82,7 @@ typedef struct upap_state { extern upap_state upap[]; -void upap_init __P((int)); void upap_authwithpeer __P((int, char *, char *)); void upap_authpeer __P((int)); -void upap_lowerup __P((int)); -void upap_lowerdown __P((int)); -void upap_input __P((int, u_char *, int)); -void upap_protrej __P((int)); -int upap_printpkt __P((u_char *, int, - void (*) __P((void *, char *, ...)), void *)); extern struct protent pap_protent; |