* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#define RCSID "$Id: auth.c,v 1.78 2002/07/13 06:24:36 kad Exp $"
+#define RCSID "$Id: auth.c,v 1.87 2002/10/12 01:28:05 fcusack Exp $"
#include <stdio.h>
#include <stddef.h>
without authenticating itself. */
static struct wordlist *noauth_addrs;
+/* Remote telephone number, if available */
+char remote_number[MAXNAMELEN];
+
+/* Wordlist giving remote telephone numbers which may connect. */
+static struct wordlist *permitted_numbers;
+
/* Extra options to apply, from the secrets file entry for the peer. */
static struct wordlist *extra_options;
static int setupapfile __P((char **));
static int privgroup __P((char **));
static int set_noauth_addr __P((char **));
+static int set_permitted_number __P((char **));
static void check_access __P((FILE *, char *));
static int wordlist_count __P((struct wordlist *));
{ "auth", o_bool, &auth_required,
"Require authentication from peer", OPT_PRIO | 1 },
{ "noauth", o_bool, &auth_required,
- "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV | OPT_A2COPY,
+ "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV,
&allow_any_ip },
{ "require-pap", o_bool, &lcp_wantoptions[0].neg_upap,
"Require PAP authentication from peer",
- OPT_PRIOSUB | OPT_A2COPY | 1, &auth_required },
+ OPT_PRIOSUB | 1, &auth_required },
{ "+pap", o_bool, &lcp_wantoptions[0].neg_upap,
"Require PAP authentication from peer",
- OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | 1, &auth_required },
- { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap,
+ OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required },
+ { "require-chap", o_bool, &auth_required,
"Require CHAP authentication from peer",
- OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MD5,
- &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
- { "+chap", o_bool, &lcp_wantoptions[0].neg_chap,
+ OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5,
+ &lcp_wantoptions[0].chap_mdtype },
+ { "+chap", o_bool, &auth_required,
"Require CHAP authentication from peer",
- OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MD5,
- &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
+ OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5,
+ &lcp_wantoptions[0].chap_mdtype },
#ifdef CHAPMS
- { "require-mschap", o_bool, &lcp_wantoptions[0].neg_chap,
+ { "require-mschap", o_bool, &auth_required,
"Require MS-CHAP authentication from peer",
- OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MICROSOFT,
- &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
- { "+mschap", o_bool, &lcp_wantoptions[0].neg_chap,
+ OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT,
+ &lcp_wantoptions[0].chap_mdtype },
+ { "+mschap", o_bool, &auth_required,
"Require MS-CHAP authentication from peer",
- OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MICROSOFT,
- &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
- { "require-mschap-v2", o_bool, &lcp_wantoptions[0].neg_chap,
+ OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT,
+ &lcp_wantoptions[0].chap_mdtype },
+ { "require-mschap-v2", o_bool, &auth_required,
"Require MS-CHAPv2 authentication from peer",
- OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MICROSOFT_V2,
- &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
- { "+mschap-v2", o_bool, &lcp_wantoptions[0].neg_chap,
+ OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2,
+ &lcp_wantoptions[0].chap_mdtype },
+ { "+mschap-v2", o_bool, &auth_required,
"Require MS-CHAPv2 authentication from peer",
- OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MICROSOFT_V2,
- &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
+ OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2,
+ &lcp_wantoptions[0].chap_mdtype },
#endif
{ "refuse-pap", o_bool, &refuse_pap,
{ "-pap", o_bool, &refuse_pap,
"Don't allow PAP authentication with peer", OPT_ALIAS | 1 },
{ "refuse-chap", o_bool, &refuse_chap,
- "Don't agree to auth to peer with CHAP", OPT_A2CLRB | MDTYPE_MD5,
+ "Don't agree to auth to peer with CHAP",
+ OPT_A2CLRB | MDTYPE_MD5,
&lcp_allowoptions[0].chap_mdtype },
{ "-chap", o_bool, &refuse_chap,
"Don't allow CHAP authentication with peer",
#ifdef CHAPMS
{ "refuse-mschap", o_bool, &refuse_mschap,
"Don't agree to auth to peer with MS-CHAP",
- OPT_A2CLRB | MDTYPE_MICROSOFT, &lcp_allowoptions[0].chap_mdtype },
+ OPT_A2CLRB | MDTYPE_MICROSOFT,
+ &lcp_allowoptions[0].chap_mdtype },
{ "-mschap", o_bool, &refuse_mschap,
"Don't allow MS-CHAP authentication with peer",
OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT,
&lcp_allowoptions[0].chap_mdtype },
{ "refuse-mschap-v2", o_bool, &refuse_mschap_v2,
"Don't agree to auth to peer with MS-CHAPv2",
- OPT_A2CLRB | MDTYPE_MICROSOFT_V2, &lcp_allowoptions[0].chap_mdtype },
+ OPT_A2CLRB | MDTYPE_MICROSOFT_V2,
+ &lcp_allowoptions[0].chap_mdtype },
{ "-mschap-v2", o_bool, &refuse_mschap_v2,
"Don't allow MS-CHAPv2 authentication with peer",
OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2,
"Set IP address(es) which can be used without authentication",
OPT_PRIV | OPT_A2LIST },
+ { "remotenumber", o_string, remote_number,
+ "Set remote telephone number for authentication", OPT_PRIO | OPT_STATIC,
+ NULL, MAXNAMELEN },
+
+ { "allow-number", o_special, (void *)set_permitted_number,
+ "Set telephone number(s) which are allowed to connect",
+ OPT_PRIV | OPT_A2LIST },
+
{ NULL }
};
}
+/*
+ * set_permitted_number - set remote telephone number(s) that may connect.
+ */
+static int
+set_permitted_number(argv)
+ char **argv;
+{
+ char *number = *argv;
+ int l = strlen(number) + 1;
+ struct wordlist *wp;
+
+ wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l);
+ if (wp == NULL)
+ novm("allow-number argument");
+ wp->word = (char *) (wp + 1);
+ wp->next = permitted_numbers;
+ BCOPY(number, wp->word, l);
+ permitted_numbers = wp;
+ return 1;
+}
+
+
/*
* An Open on LCP has requested a change from Dead to Establish phase.
* Do what's necessary to bring the physical layer up.
{
lcp_options *go = &lcp_gotoptions[unit];
+ /* Log calling number. */
+ if (*remote_number)
+ notice("peer from calling number %q authorized", remote_number);
+
/*
* If the peer had to authenticate, run the auth-up script now.
*/
start_networks(unit)
int unit;
{
- static int started = 0;
int i;
struct protent *protp;
int ecp_required, mppe_required;
- if (!started) {
- started = 1;
- new_phase(PHASE_NETWORK);
+ new_phase(PHASE_NETWORK);
#ifdef HAVE_MULTILINK
- if (multilink) {
- if (mp_join_bundle()) {
- if (updetach && !nodetach)
- detach();
- return;
- }
+ if (multilink) {
+ if (mp_join_bundle()) {
+ if (updetach && !nodetach)
+ detach();
+ return;
}
+ }
#endif /* HAVE_MULTILINK */
#ifdef PPP_FILTER
- if (!demand)
- set_filters(&pass_filter, &active_filter);
+ if (!demand)
+ set_filters(&pass_filter, &active_filter);
#endif
- /* Start CCP and ECP */
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if ((protp->protocol == PPP_ECP || protp->protocol == PPP_CCP)
- && protp->enabled_flag && protp->open != NULL)
- (*protp->open)(0);
- }
+ /* Start CCP and ECP */
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if ((protp->protocol == PPP_ECP || protp->protocol == PPP_CCP)
+ && protp->enabled_flag && protp->open != NULL)
+ (*protp->open)(0);
/*
- * Bring up other network protocols after encryption has completed.
- * OPENED here merely means that negotiation has completed. It is
- * up to the protocol to correctly terminate or disable LCP/NCP
- * based on the result of the negotiation.
+ * Bring up other network protocols iff encryption is not required.
*/
ecp_required = ecp_gotoptions[unit].required;
mppe_required = ccp_gotoptions[unit].mppe;
- if ((!ecp_required && !mppe_required)
- || (ecp_required && ecp_fsm[unit].state == OPENED)
- || (mppe_required && ccp_fsm[unit].state == OPENED)) {
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->protocol < 0xC000
- && protp->protocol != PPP_CCP && protp->protocol != PPP_ECP
- && protp->enabled_flag && protp->open != NULL) {
- (*protp->open)(0);
- ++num_np_open;
- }
+ if (!ecp_required && !mppe_required)
+ continue_networks(unit);
+}
- if (num_np_open == 0)
- /* nothing to do */
- lcp_close(0, "No network protocols running");
- }
+void
+continue_networks(unit)
+ int unit;
+{
+ int i;
+ struct protent *protp;
+
+ /*
+ * Start the "real" network protocols.
+ */
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->protocol < 0xC000
+ && protp->protocol != PPP_CCP && protp->protocol != PPP_ECP
+ && protp->enabled_flag && protp->open != NULL) {
+ (*protp->open)(0);
+ ++num_np_open;
+ }
+
+ if (num_np_open == 0)
+ /* nothing to do */
+ lcp_close(0, "No network protocols running");
}
/*
case PPP_OCTETS_DIRECTION_OUT:
used = link_stats.bytes_out;
break;
- case PPP_OCTETS_DIRECTION_MAX:
+ case PPP_OCTETS_DIRECTION_MAXOVERAL:
+ case PPP_OCTETS_DIRECTION_MAXSESSION:
used = (link_stats.bytes_in > link_stats.bytes_out) ? link_stats.bytes_in : link_stats.bytes_out;
break;
default:
default_auth = 1;
}
+ /* If we selected any CHAP flavors, we should probably negotiate it. :-) */
+ if (wo->chap_mdtype)
+ wo->neg_chap = 1;
+
/* If authentication is required, ask peer for CHAP or PAP. */
if (auth_required) {
allow_any_ip = 0;
ret = UPAP_AUTHACK;
if (uselogin || login_secret) {
/* login option or secret is @login */
- ret = plogin(user, passwd, msg);
- if (ret == UPAP_AUTHNAK)
- warn("PAP login failure for %s", user);
- else
+ if ((ret = plogin(user, passwd, msg)) == UPAP_AUTHACK)
used_login = 1;
}
if (secret[0] != 0 && !login_secret) {
/* password given in pap-secrets - must match */
if ((cryptpap || strcmp(passwd, secret) != 0)
- && strcmp(crypt(passwd, secret), secret) != 0) {
+ && strcmp(crypt(passwd, secret), secret) != 0)
ret = UPAP_AUTHNAK;
- warn("PAP authentication failure for %s", user);
- }
}
}
fclose(f);
tty = devnam;
if (strncmp(tty, "/dev/", 5) == 0)
tty += 5;
- logwtmp(tty, user, remote_name); /* Add wtmp login entry */
+ logwtmp(tty, user, ifname); /* Add wtmp login entry */
#if defined(_PATH_LASTLOG) && !defined(USE_PAM)
if (pw != (struct passwd *)NULL) {
return 0;
}
+/*
+ * auth_number - check whether the remote number is allowed to connect.
+ * Returns 1 if authorized, 0 otherwise.
+ */
+int
+auth_number()
+{
+ struct wordlist *wp = permitted_numbers;
+ int l;
+
+ /* Allow all if no authorization list. */
+ if (!wp)
+ return 1;
+
+ /* Allow if we have a match in the authorization list. */
+ while (wp) {
+ /* trailing '*' wildcard */
+ l = strlen(wp->word);
+ if ((wp->word)[l - 1] == '*')
+ l--;
+ if (!strncasecmp(wp->word, remote_number, l))
+ return 1;
+ wp = wp->next;
+ }
+
+ return 0;
+}
+
/*
* check_access - complain if a secret file has too-liberal permissions.
*/