📄 auth.c
字号:
#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) { pw->pw_passwd = ""; } else { 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); }#else epasswd = crypt(passwd, pw->pw_passwd); if (strcmp(epasswd, pw->pw_passwd)) { return (UPAP_AUTHNAK); }#endif do_syslog(LOG_INFO, "user %s logged in", user); /* * Write a wtmp entry for this user. */ tty = strrchr(devnam, '/'); if (tty == NULL) tty = devnam; else tty++;#ifdef LOGWTMP_WORKED logwtmp(tty, user, ""); /* Add wtmp login entry -- which just returned 1 */#endif logged_in = TRUE; return (UPAP_AUTHACK);}/* * logout - Logout the user. */static voidlogout(){ char *tty; tty = strrchr(devnam, '/'); if (tty == NULL) tty = devnam; else tty++;#ifdef LOGWTMP_WORKED logwtmp(tty, "", ""); /* Wipe out wtmp logout entry */#endif logged_in = FALSE;}/* * null_login - Check if a username of "" and a password of "" are * acceptable, and iff so, set the list of acceptable IP addresses * and return 1. */static intnull_login(unit) int unit;{ char *filename; FILE *f; int i, ret; struct wordlist *addrs; char secret[MAXWORDLEN]; /* * Open the file of upap secrets and scan for a suitable secret. * We don't accept a wildcard client. */ filename = _PATH_UPAPFILE; addrs = NULL; f = fopen(filename, "r"); if (f == NULL) return 0; check_access(f, filename); i = scan_authfile(f, "", our_name, secret, sizeof(secret), &addrs, filename); ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0; if (ret) { if (addresses[unit] != NULL) free_wordlist(addresses[unit]); addresses[unit] = addrs; } fclose(f); return ret;}/* * get_upap_passwd - get a password for authenticating ourselves with * our peer using PAP. Returns 1 on success, 0 if no suitable password * could be found. */static intget_upap_passwd(){ char *filename; FILE *f; struct wordlist *addrs; char secret[MAXWORDLEN]; filename = _PATH_UPAPFILE; addrs = NULL; f = fopen(filename, "r"); if (f == NULL) return 0; check_access(f, filename); if (scan_authfile(f, user, remote_name, secret, sizeof(secret), NULL, filename) < 0) return 0; strncpy(passwd, secret, MAXSECRETLEN); passwd[MAXSECRETLEN-1] = 0; return 1;}/* * have_upap_secret - check whether we have a PAP file with any * secrets that we could possibly use for authenticating the peer. */static inthave_upap_secret(){ FILE *f; int ret; char *filename; filename = _PATH_UPAPFILE; f = fopen(filename, "r"); if (f == NULL) return 0; ret = scan_authfile(f, NULL, our_name, NULL, 0, NULL, filename); fclose(f); if (ret < 0) return 0; return 1;}/* * have_chap_secret - check whether we have a CHAP file with a * secret that we could possibly use for authenticating `client' * on `server'. Either can be the null string, meaning we don't * know the identity yet. */static inthave_chap_secret(client, server) char *client; char *server;{ FILE *f; int ret; char *filename; filename = _PATH_CHAPFILE; f = fopen(filename, "r"); if (f == NULL) return 0; if (client[0] == 0) client = NULL; else if (server[0] == 0) server = NULL; ret = scan_authfile(f, client, server, NULL, 0, NULL, filename); fclose(f); if (ret < 0) return 0; return 1;}/* * get_secret - open the CHAP secret file and return the secret * for authenticating the given client on the given server. * (We could be either client or server). */intget_secret(unit, client, server, secret, secret_len, save_addrs) int unit; char *client; char *server; char *secret; int *secret_len; int save_addrs;{ FILE *f; int ret, len; char *filename; struct wordlist *addrs; char secbuf[MAXWORDLEN]; filename = _PATH_CHAPFILE; addrs = NULL; secbuf[0] = 0; f = fopen(filename, "r"); if (f == NULL) { do_syslog(LOG_ERR, "Can't open chap secret file %s: %m", filename); return 0; } check_access(f, filename); ret = scan_authfile(f, client, server, secbuf, sizeof(secbuf), &addrs, filename); fclose(f); if (ret < 0) return 0; if (save_addrs) { if (addresses[unit] != NULL) free_wordlist(addresses[unit]); addresses[unit] = addrs; } len = strlen(secbuf); if (len > MAXSECRETLEN) { do_syslog(LOG_ERR, "Secret for %s on %s is too long", client, server); len = MAXSECRETLEN; } BCOPY(secbuf, secret, len); *secret_len = len; return 1;}/* * auth_ip_addr - check whether the peer is authorized to use * a given IP address. Returns 1 if authorized, 0 otherwise. */intauth_ip_addr(unit, addr) int unit; u_int32_t addr;{ u_int32_t a; struct hostent *hp; struct wordlist *addrs; /* don't allow loopback or multicast address */ if (bad_ip_adrs(addr)) return 0; if ((addrs = addresses[unit]) == NULL) return 1; /* no restriction */ for (; addrs != NULL; addrs = addrs->next) { /* "-" means no addresses authorized */ if (strcmp(addrs->word, "-") == 0) break; if ((a = inet_addr(addrs->word)) == -1) { if ((hp = gethostbyname(addrs->word)) == NULL) { do_syslog(LOG_WARNING, "unknown host %s in auth. address list", addrs->word); continue; } else a = *(u_int32_t *)hp->h_addr; } if (addr == a) return 1; } return 0; /* not in list => can't have it */}/* * bad_ip_adrs - return 1 if the IP address is one we don't want * to use, such as an address in the loopback net or a multicast address. * addr is in network byte order. */intbad_ip_adrs(addr) u_int32_t addr;{ addr = ntohl(addr); return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || IN_MULTICAST(addr) || IN_BADCLASS(addr);}/* * check_access - complain if a secret file has too-liberal permissions. */voidcheck_access(f, filename) FILE *f; char *filename;{ struct stat sbuf; if (fstat(fileno(f), &sbuf) < 0) { do_syslog(LOG_WARNING, "cannot stat secret file %s: %m", filename); } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { do_syslog(LOG_WARNING, "Warning - secret file %s has world and/or group access", filename); }}/* * scan_authfile - Scan an authorization file for a secret suitable * for authenticating `client' on `server'. The return value is -1 * if no secret is found, otherwise >= 0. The return value has * NONWILD_CLIENT set if the secret didn't have "*" for the client, and * NONWILD_SERVER set if the secret didn't have "*" for the server. * Any following words on the line (i.e. address authorization * info) are placed in a wordlist and returned in *addrs. */static intscan_authfile(f, client, server, secret, max_secret, addrs, filename) FILE *f; char *client; char *server; char *secret; int max_secret; struct wordlist **addrs; char *filename;{ int newline, xxx; int got_flag, best_flag; FILE *sf; struct wordlist *ap, *addr_list, *addr_last; char word[MAXWORDLEN]; char atfile[MAXWORDLEN]; if (addrs != NULL) *addrs = NULL; addr_list = NULL; if (!getword(f, word, &newline, filename)) return -1; /* file is empty??? */ newline = 1; best_flag = -1; for (;;) { /* * Skip until we find a word at the start of a line. */ while (!newline && getword(f, word, &newline, filename)) ; if (!newline) break; /* got to end of file */ /* * Got a client - check if it's a match or a wildcard. */ got_flag = 0; if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { newline = 0; continue; } if (!ISWILD(word)) got_flag = NONWILD_CLIENT; /* * Now get a server and check if it matches. */ if (!getword(f, word, &newline, filename)) break; if (newline) continue; if (server != NULL && strcmp(word, server) != 0 && !ISWILD(word)) continue; if (!ISWILD(word)) got_flag |= NONWILD_SERVER; /* * Got some sort of a match - see if it's better than what * we have already. */ if (got_flag <= best_flag) continue; /* * Get the secret. */ if (!getword(f, word, &newline, filename)) break; if (newline) continue; /* * Special syntax: @filename means read secret from file. */ if (word[0] == '@') { strncpy2(atfile, word+1, sizeof(atfile)); if ((sf = fopen(atfile, "r")) == NULL) { do_syslog(LOG_WARNING, "can't open indirect secret file %s", atfile); continue; } check_access(sf, atfile); if (!getword(sf, word, &xxx, atfile)) { do_syslog(LOG_WARNING, "no secret in indirect secret file %s", atfile); fclose(sf); continue; } fclose(sf); } if (secret != NULL) strncpy2(secret, word, max_secret); best_flag = got_flag; /* * Now read address authorization info and make a wordlist. */ if (addr_list) free_wordlist(addr_list); addr_list = addr_last = NULL; for (;;) { if (!getword(f, word, &newline, filename) || newline) break; ap = (struct wordlist *) malloc(sizeof(struct wordlist) + strlen(word)); if (ap == NULL) novm("authorized addresses"); ap->next = NULL; /* TODO: check lengths should be ok, alloced correctly above.*/ strcpy(ap->word, word); if (addr_list == NULL) addr_list = ap; else addr_last->next = ap; addr_last = ap; } if (!newline) break; } if (addrs != NULL) *addrs = addr_list; else if (addr_list != NULL) free_wordlist(addr_list); return best_flag;}/* * free_wordlist - release memory allocated for a wordlist. */static voidfree_wordlist(wp) struct wordlist *wp;{ struct wordlist *next; while (wp != NULL) { next = wp->next; free(wp); wp = next; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -