*/
#ifndef lint
-static char rcsid[] = "$Id: auth.c,v 1.29 1996/10/08 06:43:15 paulus Exp $";
+static char rcsid[] = "$Id: auth.c,v 1.30 1997/03/04 03:37:21 paulus Exp $";
#endif
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#ifdef SVR4
+#if defined(SVR4) || defined(_linux_)
#include <crypt.h>
#else
#if defined(SUNOS4) || defined(ULTRIX)
#ifdef USE_PAM
#include <security/pam_appl.h>
#include <security/pam_modules.h>
-int isexpired (struct passwd *, struct spwd *);
#endif
#ifdef HAS_SHADOW
static void network_phase __P((int));
static void check_idle __P((caddr_t));
+static void connect_time_expired __P((caddr_t));
static int login __P((char *, char *, char **, int *));
static void logout __P((void));
static int null_login __P((int));
struct wordlist **, char *));
static void free_wordlist __P((struct wordlist *));
static void auth_script __P((char *));
+static void set_allowed_addrs __P((int, struct wordlist *));
#ifdef CBCP_SUPPORT
static void callback_phase __P((int));
#endif
}
num_np_open = 0;
num_np_up = 0;
- phase = PHASE_TERMINATE;
+ if (phase != PHASE_DEAD)
+ phase = PHASE_TERMINATE;
}
/*
{
if (num_np_up == 0 && idle_time_limit > 0) {
TIMEOUT(check_idle, NULL, idle_time_limit);
+
+ /*
+ * Set a timeout to close the connection once the maximum
+ * connect time has expired.
+ */
+ if (maxconnect > 0)
+ TIMEOUT(connect_time_expired, 0, maxconnect);
}
++num_np_up;
}
}
}
+/*
+ * connect_time_expired - log a message and close the connection.
+ */
+static void
+connect_time_expired(arg)
+ caddr_t arg;
+{
+ syslog(LOG_INFO, "Connect time expired");
+ lcp_close(0, "Connect time expired"); /* Close connection */
+}
+
/*
* auth_check_options - called to check authentication options.
*/
ret = UPAP_AUTHACK;
f = fopen(filename, "r");
if (f == NULL) {
- if (!uselogin) {
- syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename);
- ret = UPAP_AUTHNAK;
- }
+ syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename);
+ ret = UPAP_AUTHNAK;
} else {
check_access(f, filename);
if (*msg == (char *) 0)
*msg = "Login ok";
*msglen = strlen(*msg);
- if (addresses[unit] != NULL)
- free_wordlist(addresses[unit]);
- addresses[unit] = addrs;
+ set_allowed_addrs(unit, addrs);
}
BZERO(passwd, sizeof(passwd));
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 HAS_SHADOW
struct spwd *spwd;
struct spwd *getspnam();
+ extern int isexpired (struct passwd *, struct spwd *); /* in libshadow.a */
#endif
pw = getpwnam(user);
#endif
/*
- * XXX If no passwd, let them login without one.
+ * If no passwd, don't let them login.
*/
- if (pw->pw_passwd != NULL && *pw->pw_passwd != '\0') {
- epasswd = crypt(passwd, pw->pw_passwd);
- if (strcmp(epasswd, pw->pw_passwd) != 0) {
- return (UPAP_AUTHNAK);
- }
- }
+ if (pw->pw_passwd == NULL || *pw->pw_passwd == '\0'
+ || strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) != 0)
+ return (UPAP_AUTHNAK);
+
#endif /* #ifdef USE_PAM */
syslog(LOG_INFO, "user %s logged in", user);
ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0;
BZERO(secret, sizeof(secret));
- if (ret) {
- if (addresses[unit] != NULL)
- free_wordlist(addresses[unit]);
- addresses[unit] = addrs;
- }
+ if (ret)
+ set_allowed_addrs(unit, addrs);
+ else
+ free_wordlist(addrs);
fclose(f);
return ret;
if (ret < 0)
return 0;
- if (save_addrs) {
- if (addresses[unit] != NULL)
- free_wordlist(addresses[unit]);
- addresses[unit] = addrs;
- }
+ if (save_addrs)
+ set_allowed_addrs(unit, addrs);
len = strlen(secbuf);
if (len > MAXSECRETLEN) {
return 1;
}
+/*
+ * set_allowed_addrs() - set the list of allowed addresses.
+ */
+static void
+set_allowed_addrs(unit, addrs)
+ int unit;
+ struct wordlist *addrs;
+{
+ if (addresses[unit] != NULL)
+ free_wordlist(addresses[unit]);
+ addresses[unit] = addrs;
+
+ /*
+ * If there's only one authorized address we might as well
+ * ask our peer for that one right away
+ */
+ if (addrs != NULL && addrs->next == NULL) {
+ char *p = addrs->word;
+ struct ipcp_options *wo = &ipcp_wantoptions[unit];
+ u_int32_t a;
+ struct hostent *hp;
+
+ if (wo->hisaddr == 0 && *p != '!' && *p != '-'
+ && strchr(p, '/') == NULL) {
+ hp = gethostbyname(p);
+ if (hp != NULL && hp->h_addrtype == AF_INET)
+ a = *(u_int32_t *)hp->h_addr;
+ else
+ a = inet_addr(p);
+ if (a != (u_int32_t) -1)
+ wo->hisaddr = a;
+ }
+ }
+}
+
/*
* auth_ip_addr - check whether the peer is authorized to use
* a given IP address. Returns 1 if authorized, 0 otherwise.
return 0;
if (addrs == NULL)
- return 1; /* no restriction */
+ return !auth_required; /* no addresses authorized */
for (; addrs != NULL; addrs = addrs->next) {
- /* "-" means no addresses authorized */
+ /* "-" means no addresses authorized, "*" means any address allowed */
ptr_word = addrs->word;
if (strcmp(ptr_word, "-") == 0)
break;
+ if (strcmp(ptr_word, "*") == 0)
+ return 1;
accept = 1;
if (*ptr_word == '!') {
hp = gethostbyname(ptr_word);
if (hp != NULL && hp->h_addrtype == AF_INET) {
- a = *(u_int32_t *)hp->h_addr;
- mask = ~ (u_int32_t) 0; /* are we sure we want this? */
+ a = *(u_int32_t *)hp->h_addr;
} else {
np = getnetbyname (ptr_word);
- if (np != NULL && np->n_addrtype == AF_INET)
+ if (np != NULL && np->n_addrtype == AF_INET) {
a = htonl (*(u_int32_t *)np->n_net);
- else
+ if (ptr_mask == NULL) {
+ /* calculate appropriate mask for net */
+ ah = ntohl(a);
+ if (IN_CLASSA(ah))
+ mask = IN_CLASSA_NET;
+ else if (IN_CLASSB(ah))
+ mask = IN_CLASSB_NET;
+ else if (IN_CLASSC(ah))
+ mask = IN_CLASSC_NET;
+ }
+ } else {
a = inet_addr (ptr_word);
- if (ptr_mask == NULL) {
- /* calculate appropriate mask for net */
- ah = ntohl(a);
- if (IN_CLASSA(ah))
- mask = IN_CLASSA_NET;
- else if (IN_CLASSB(ah))
- mask = IN_CLASSB_NET;
- else if (IN_CLASSC(ah))
- mask = IN_CLASSC_NET;
}
}
"unknown host %s in auth. address list",
addrs->word);
else
+ /* Here a and addr are in network byte order,
+ and mask is in host order. */
if (((addr ^ a) & htonl(mask)) == 0)
return accept;
}