* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#define RCSID "$Id: auth.c,v 1.63 2000/04/04 07:06:49 paulus Exp $"
+#define RCSID "$Id: auth.c,v 1.67 2000/08/01 01:38:29 paulus Exp $"
#include <stdio.h>
#include <stddef.h>
static enum script_state auth_script_state = s_down;
static pid_t auth_script_pid = 0;
+static int used_login; /* peer authenticated against login database */
+
/*
* Option variables.
*/
static int privgroup __P((char **));
static int set_noauth_addr __P((char **));
static void check_access __P((FILE *, char *));
+static int wordlist_count __P((struct wordlist *));
/*
* Authentication-related options.
"Use system password database for PAP", 1 },
{ "papcrypt", o_bool, &cryptpap,
"PAP passwords are encrypted", 1 },
- { "+ua", o_special, setupapfile,
+ { "+ua", o_special, (void *)setupapfile,
"Get PAP user and password from file" },
{ "password", o_string, passwd,
"Password for authenticating us to the peer", OPT_STATIC,
NULL, MAXSECRETLEN },
- { "privgroup", o_special, privgroup,
+ { "privgroup", o_special, (void *)privgroup,
"Allow group members to use privileged options", OPT_PRIV },
- { "allow-ip", o_special, set_noauth_addr,
+ { "allow-ip", o_special, (void *)set_noauth_addr,
"Set IP address(es) which can be used without authentication",
OPT_PRIV },
{ NULL }
char **argv;
{
char *addr = *argv;
- int l = strlen(addr);
+ int l = strlen(addr) + 1;
struct wordlist *wp;
- wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l + 1);
+ wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l);
if (wp == NULL)
novm("allow-ip argument");
wp->word = (char *) (wp + 1);
* boot it out.
*/
if (noauth_addrs != NULL) {
- set_allowed_addrs(unit, noauth_addrs, NULL);
- } else if (!wo->neg_upap || !null_login(unit)) {
+ set_allowed_addrs(unit, NULL, NULL);
+ } else if (!wo->neg_upap || uselogin || !null_login(unit)) {
warn("peer refused to authenticate: terminating link");
lcp_close(unit, "peer refused to authenticate");
status = EXIT_PEER_AUTH_FAILED;
}
new_phase(PHASE_AUTHENTICATE);
+ used_login = 0;
auth = 0;
if (go->neg_chap) {
ChapAuthPeer(unit, our_name, go->chap_mdtype);
new_phase(PHASE_NETWORK);
#ifdef HAVE_MULTILINK
- if (multilink)
- if (mp_join_bundle())
+ if (multilink) {
+ if (mp_join_bundle()) {
+ if (updetach && !nodetach)
+ detach();
return;
+ }
+ }
#endif /* HAVE_MULTILINK */
-#if 0
+#ifdef PPP_FILTER
if (!demand)
set_filters(&pass_filter, &active_filter);
#endif
check_access(f, filename);
if (scan_authfile(f, user, our_name, secret, &addrs, &opts, filename) < 0) {
warn("no PAP secret found for %s", user);
- } else if (secret[0] != 0) {
- /* password given in pap-secrets - must match */
- if ((!cryptpap && strcmp(passwd, secret) == 0)
- || strcmp(crypt(passwd, secret), secret) == 0)
- ret = UPAP_AUTHACK;
- else
- warn("PAP authentication failure for %s", user);
- } else if (uselogin) {
- /* empty password in pap-secrets and login option */
- ret = plogin(user, passwd, msg);
- if (ret == UPAP_AUTHNAK)
- warn("PAP login failure for %s", user);
} else {
- /* empty password in pap-secrets and login option not used */
+ /*
+ * If the secret is "@login", it means to check
+ * the password against the login database.
+ */
+ int login_secret = strcmp(secret, "@login") == 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
+ 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) {
+ ret = UPAP_AUTHNAK;
+ warn("PAP authentication failure for %s", user);
+ }
+ }
}
fclose(f);
}
struct wordlist *opts;
{
int n;
- struct wordlist *ap, **pap;
+ struct wordlist *ap, **plink;
struct permitted_ip *ip;
char *ptr_word, *ptr_mask;
struct hostent *hp;
/*
* Count the number of IP addresses given.
*/
- for (n = 0, pap = &addrs; (ap = *pap) != NULL; pap = &ap->next)
- ++n;
+ n = wordlist_count(addrs) + wordlist_count(noauth_addrs);
if (n == 0)
return;
ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip));
if (ip == 0)
return;
+ /* temporarily append the noauth_addrs list to addrs */
+ for (plink = &addrs; *plink != NULL; plink = &(*plink)->next)
+ ;
+ *plink = noauth_addrs;
+
n = 0;
for (ap = addrs; ap != NULL; ap = ap->next) {
/* "-" means no addresses authorized, "*" means any address allowed */
if (~mask == 0 && suggested_ip == 0)
suggested_ip = a;
}
+ *plink = NULL;
ip[n].permit = 0; /* make the last entry forbid all addresses */
ip[n].base = 0; /* to terminate the list */
if (newline)
continue;
- /*
- * Special syntax: @filename means read secret from file.
- */
- if (word[0] == '@') {
- strlcpy(atfile, word+1, sizeof(atfile));
- if ((sf = fopen(atfile, "r")) == NULL) {
- warn("can't open indirect secret file %s", atfile);
- continue;
- }
- check_access(sf, atfile);
- if (!getword(sf, word, &xxx, atfile)) {
- warn("no secret in indirect secret file %s", atfile);
+ if (secret != NULL) {
+ /*
+ * Special syntax: @/pathname means read secret from file.
+ */
+ if (word[0] == '@' && word[1] == '/') {
+ strlcpy(atfile, word+1, sizeof(atfile));
+ if ((sf = fopen(atfile, "r")) == NULL) {
+ warn("can't open indirect secret file %s", atfile);
+ continue;
+ }
+ check_access(sf, atfile);
+ if (!getword(sf, word, &xxx, atfile)) {
+ warn("no secret in indirect secret file %s", atfile);
+ fclose(sf);
+ continue;
+ }
fclose(sf);
- continue;
}
- fclose(sf);
- }
- if (secret != NULL)
strlcpy(lsecret, word, sizeof(lsecret));
+ }
/*
* Now read address authorization info and make a wordlist.
return best_flag;
}
+/*
+ * wordlist_count - return the number of items in a wordlist
+ */
+static int
+wordlist_count(wp)
+ struct wordlist *wp;
+{
+ int n;
+
+ for (n = 0; wp != NULL; wp = wp->next)
+ ++n;
+ return n;
+}
+
/*
* free_wordlist - release memory allocated for a wordlist.
*/