diff options
author | green <green@FreeBSD.org> | 1999-07-26 07:57:35 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 1999-07-26 07:57:35 +0000 |
commit | 9fb486a915eda92a5fba5213f46597422f06cc33 (patch) | |
tree | 9ce03d3c2fea3ad964ab720922e138f0e340f507 | |
parent | 6023cfb17a2c0a7e428320fe91ceb9188a38e49b (diff) | |
download | FreeBSD-src-9fb486a915eda92a5fba5213f46597422f06cc33.zip FreeBSD-src-9fb486a915eda92a5fba5213f46597422f06cc33.tar.gz |
Here goes, the "clear up any possible confusion" commit.
I've taken time to write up comments for the ident code tonight,
so there should no longer be any confusion about the purpouse of
whatever is in there. Wow, me commenting code... who'd have thought
that would happen?
Reviewed by: DES
-rw-r--r-- | usr.sbin/inetd/builtins.c | 76 |
1 files changed, 65 insertions, 11 deletions
diff --git a/usr.sbin/inetd/builtins.c b/usr.sbin/inetd/builtins.c index e3d2013..2ad656c 100644 --- a/usr.sbin/inetd/builtins.c +++ b/usr.sbin/inetd/builtins.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: builtins.c,v 1.11 1999/07/24 17:06:05 green Exp $ + * $Id: builtins.c,v 1.12 1999/07/25 23:15:03 green Exp $ * */ @@ -307,15 +307,9 @@ echo_stream(s, sep) /* Echo service -- echo data back */ * support. */ -/* - * NOTE: If any of the asprintf()s here fail, rest assured that faulting - * in the buffers for using snprintf() would have also failed. - * Asprintf() is the proper way to do what we do. - */ - /* ARGSUSED */ void -iderror(lport, fport, s, er) +iderror(lport, fport, s, er) /* Generic ident_stream error-sending func */ int lport, fport, s, er; { char *p; @@ -334,7 +328,7 @@ iderror(lport, fport, s, er) /* ARGSUSED */ void -ident_stream(s, sep) /* Ident service */ +ident_stream(s, sep) /* Ident service (AKA "auth") */ int s; struct servtab *sep; { @@ -353,8 +347,17 @@ ident_stream(s, sep) /* Ident service */ u_short lport, fport; inetd_setproctitle(sep->se_service, s); + /* + * Reset getopt() since we are a fork() but not an exec() from + * a parent which used getopt() already. + */ optind = 1; optreset = 1; + /* + * Take the internal argument vector and count it out to make an + * argument count for getopt. This can be used for any internal + * service to read arguments and use getopt() easily. + */ for (av = sep->se_argv; *av; av++) argc++; if (argc) { @@ -402,6 +405,12 @@ ident_stream(s, sep) /* Ident service */ len = sizeof(sin[1]); if (getpeername(s, (struct sockaddr *)&sin[1], &len) == -1) iderror(0, 0, s, errno); + /* + * We're going to prepare for and execute reception of a + * packet of data from the user. The data is in the format + * "local_port , foreign_port\r\n" (with local being the + * server's port and foreign being the client's.) + */ FD_ZERO(&fdset); FD_SET(s, &fdset); if (select(s + 1, &fdset, NULL, NULL, &tv) == -1) @@ -416,17 +425,30 @@ ident_stream(s, sep) /* Ident service */ buf[len] = '\0'; if (sscanf(buf, "%hu , %hu", &lport, &fport) != 2) iderror(0, 0, s, 0); - if (!rflag) + if (!rflag) /* Send HIDDEN-USER immediately if not "real" */ iderror(lport, fport, s, -1); + /* + * We take the input and construct an array of two sockaddr_ins + * which contain the local address information and foreign + * address information, respectively, used to look up the + * credentials for the socket (which are returned by the + * sysctl "net.inet.tcp.getcred" when we call it.) The + * arrays have been filled in above via get{peer,sock}name(), + * so right here we are only setting the ports. + */ sin[0].sin_port = htons(lport); sin[1].sin_port = htons(fport); len = sizeof(uc); if (sysctlbyname("net.inet.tcp.getcred", &uc, &len, sin, sizeof(sin)) == -1) iderror(lport, fport, s, errno); - pw = getpwuid(uc.cr_uid); + pw = getpwuid(uc.cr_uid); /* Look up the pw to get the username */ if (pw == NULL) iderror(lport, fport, s, errno); + /* + * If enabled, we check for a file named ".noident" in the user's + * home directory. If found, we return HIDDEN-USER. + */ if (nflag) { if (asprintf(&p, "%s/.noident", pw->pw_dir) == -1) iderror(lport, fport, s, errno); @@ -436,13 +458,30 @@ ident_stream(s, sep) /* Ident service */ } free(p); } + /* + * Here, if enabled, we read a user's ".fakeid" file in their + * home directory. It consists of a line containing the name + * they want. + */ if (fflag) { FILE *fakeid = NULL; if (asprintf(&p, "%s/.fakeid", pw->pw_dir) == -1) iderror(lport, fport, s, errno); + /* + * Here we set ourself to effectively be the user, so we don't + * open any files we have no permission to open, especially + * symbolic links to sensitive root-owned files or devices. + */ seteuid(pw->pw_uid); setegid(pw->pw_gid); + /* + * If we were to lstat() here, it would do no good, since it + * would introduce a race condition and could be defeated. + * Therefore, we open the file we have permissions to open + * and if it's not a regular file, we close it and end up + * returning the user's real username. + */ fakeid = fopen(p, "r"); free(p); if (fakeid != NULL && @@ -454,13 +493,27 @@ ident_stream(s, sep) /* Ident service */ goto printit; } fclose(fakeid); + /* + * Usually, the file will have the desired identity + * in the form "identity\n", so we use strtok() to + * end the string (which fgets() doesn't do.) + */ strtok(buf, "\r\n"); + /* User names of >16 characters are invalid */ if (strlen(buf) > 16) buf[16] = '\0'; cp = buf; + /* Allow for beginning white space... */ while (isspace(*cp)) cp++; + /* ...and ending white space. */ strtok(cp, " \t"); + /* + * If the name is a zero-length string or matches + * the name of another user, it's invalid, so + * we will return their real identity instead. + */ + if (!*cp || getpwnam(cp)) cp = getpwuid(uc.cr_uid)->pw_name; } else @@ -468,6 +521,7 @@ ident_stream(s, sep) /* Ident service */ } else cp = pw->pw_name; printit: + /* Finally, we make and send the reply. */ if (asprintf(&p, "%d , %d : USERID : %s : %s\r\n", lport, fport, osname, cp) == -1) { syslog(LOG_ERR, "asprintf: %m"); |