From owner-freebsd-audit Mon Jul 22 8:58:31 2002 Delivered-To: freebsd-audit@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3222C37B400; Mon, 22 Jul 2002 08:58:13 -0700 (PDT) Received: from chiark.greenend.org.uk (chiark.greenend.org.uk [212.135.138.206]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4661243E31; Mon, 22 Jul 2002 08:58:10 -0700 (PDT) (envelope-from fanf@chiark.greenend.org.uk) Received: from fanf by chiark.greenend.org.uk with local (Exim 3.12 #1) id 17WfZX-0000Pt-00 (Debian); Mon, 22 Jul 2002 16:58:07 +0100 Date: Mon, 22 Jul 2002 16:58:07 +0100 From: Tony Finch To: freebsd-net@freebsd.org, freebsd-audit@freebsd.org Cc: dwmalone@freebsd.org, dot@dotat.at Subject: [PATCH] inetd auth logging Message-ID: <20020722165807.D13903@chiark.greenend.org.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i Sender: owner-freebsd-audit@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG The patch below adds a -l option to turn on logging of the inetd builtin auth (RFC 1413) service. It's mainly intended for use with the -g option, so that there is a record in the logs of the correspondence between the nonce that inetd returns and the real username associated with the connection. Tony. -- f.a.n.finch http://dotat.at/ VIKING NORTH UTSIRE: NORTHWEST 5 OR 6 DECREASING 4. SHOWERS. MODERATE OR GOOD. --- src/usr.sbin/inetd/builtins.c 17 Jul 2001 10:45:03 -0000 1.19.2.6 +++ src/usr.sbin/inetd/builtins.c 22 Jul 2002 15:52:21 -0000 @@ -327,25 +327,6 @@ /* ARGSUSED */ void -iderror(lport, fport, s, er) /* Generic ident_stream error-sending func */ - int lport, fport, s; - const char *er; -{ - char *p; - - asprintf(&p, "%d , %d : ERROR : %s\r\n", lport, fport, er); - if (p == NULL) { - syslog(LOG_ERR, "asprintf: %m"); - exit(EX_OSERR); - } - send(s, p, strlen(p), MSG_EOF); - free(p); - - exit(0); -} - -/* ARGSUSED */ -void ident_stream(s, sep) /* Ident service (AKA "auth") */ int s; struct servtab *sep; @@ -366,10 +347,11 @@ fd_set fdset; char buf[BUFSIZE], *p, **av, *osname = NULL, e; char idbuf[MAXLOGNAME] = ""; /* Big enough to hold uid in decimal. */ + const char *error = ID_UNKNOWN; socklen_t socklen; ssize_t ssize; size_t size, bufsiz; - int c, fflag = 0, nflag = 0, rflag = 0, argc = 0; + int c, fflag = 0, lflag = 0, nflag = 0, rflag = 0, argc = 0; int gflag = 0, iflag = 0, Fflag = 0, getcredfail = 0, onreadlen; u_short lport, fport; @@ -392,7 +374,7 @@ size_t i; u_int32_t rnd32; - while ((c = getopt(argc, sep->se_argv, "d:fFgino:rt:")) != -1) + while ((c = getopt(argc, sep->se_argv, "d:fFgilno:rt:")) != -1) switch (c) { case 'd': if (!gflag) @@ -431,6 +413,9 @@ case 'i': iflag = 1; break; + case 'l': + lflag = 1; + break; case 'n': nflag = 1; break; @@ -460,7 +445,7 @@ } if (osname == NULL) { if (uname(&un) == -1) - iderror(0, 0, s, ID_UNKNOWN); + goto printerror; osname = un.sysname; } @@ -493,14 +478,14 @@ break; FD_SET(s, &fdset); if (select(s + 1, &fdset, NULL, NULL, &tv) == -1) - iderror(0, 0, s, ID_UNKNOWN); + goto printerror; if (ioctl(s, FIONREAD, &onreadlen) == -1) - iderror(0, 0, s, ID_UNKNOWN); + goto printerror; if ((size_t)onreadlen > bufsiz) onreadlen = bufsiz; ssize = read(s, &buf[size], (size_t)onreadlen); if (ssize == -1) - iderror(0, 0, s, ID_UNKNOWN); + goto printerror; else if (ssize == 0) break; bufsiz -= ssize; @@ -510,22 +495,22 @@ } buf[size] = '\0'; /* Read two characters, and check for a delimiting character */ - if (sscanf(buf, "%hu , %hu%c", &lport, &fport, &e) != 3 || isdigit(e)) - iderror(0, 0, s, ID_INVALID); - - /* Send garbage? */ - if (gflag) - goto printit; + if (sscanf(buf, "%hu , %hu%c", &lport, &fport, &e) != 3 || isdigit(e)) { + error = ID_INVALID; + goto printerror; + } /* * If not "real" (-r), send a HIDDEN-USER error for everything. - * If -d is used to set a fallback username, this is used to - * override it, and the fallback is returned instead. + * If -d or -g is used to set a fallback username, this is used + * to override it, and the fallback is returned instead. + * If we are logging we have to do a bit more work. */ - if (!rflag) { - if (*idbuf == '\0') - iderror(lport, fport, s, ID_HIDDEN); - goto printit; + if (!lflag && (gflag || !rflag)) { + if (*idbuf != '\0') + goto printit; + error = ID_HIDDEN; + goto printerror; } /* @@ -537,12 +522,12 @@ */ socklen = sizeof(ss[0]); if (getsockname(s, (struct sockaddr *)&ss[0], &socklen) == -1) - iderror(lport, fport, s, ID_UNKNOWN); + goto printerror; socklen = sizeof(ss[1]); if (getpeername(s, (struct sockaddr *)&ss[1], &socklen) == -1) - iderror(lport, fport, s, ID_UNKNOWN); + goto printerror; if (ss[0].ss_family != ss[1].ss_family) - iderror(lport, fport, s, ID_UNKNOWN); + goto printerror; size = sizeof(uc); switch (ss[0].ss_family) { case AF_INET: @@ -570,17 +555,31 @@ break; } if (getcredfail != 0) { - if (*idbuf == '\0') - iderror(lport, fport, s, - getcredfail == ENOENT ? ID_NOUSER : ID_UNKNOWN); - goto printit; + if (*idbuf != '\0') + goto printit; + if (getcredfail == ENOENT) + error = ID_NOUSER; + goto printerror; } /* Look up the pw to get the username and home directory*/ errno = 0; pw = getpwuid(uc.cr_uid); - if (pw == NULL) - iderror(lport, fport, s, errno == 0 ? ID_NOUSER : ID_UNKNOWN); + if (pw == NULL) { + if (*idbuf != '\0') + goto printit; + if (errno == 0) + error = ID_NOUSER; + goto printerror; + } + + /* Now do the stuff that we deferred because we are logging. */ + if (gflag || !rflag) { + if (*idbuf != '\0') + goto printit; + error = ID_HIDDEN; + goto printerror; + } if (iflag) snprintf(idbuf, sizeof(idbuf), "%u", (unsigned)pw->pw_uid); @@ -593,10 +592,11 @@ */ if (nflag) { if (asprintf(&p, "%s/.noident", pw->pw_dir) == -1) - iderror(lport, fport, s, ID_UNKNOWN); + goto printerror; if (lstat(p, &sb) == 0) { free(p); - iderror(lport, fport, s, ID_HIDDEN); + error = ID_HIDDEN; + goto printerror; } free(p); } @@ -615,9 +615,9 @@ * symbolic links to sensitive root-owned files or devices. */ if (initgroups(pw->pw_name, pw->pw_gid) == -1) - iderror(lport, fport, s, ID_UNKNOWN); + goto printerror; if (seteuid(pw->pw_uid) == -1) - iderror(lport, fport, s, ID_UNKNOWN); + goto printerror; /* * We can't stat() here since that would be a race * condition. @@ -626,7 +626,7 @@ * returning the user's real username. */ if (asprintf(&p, "%s/.fakeid", pw->pw_dir) == -1) - iderror(lport, fport, s, ID_UNKNOWN); + goto printerror; fakeid_fd = open(p, O_RDONLY | O_NONBLOCK); free(p); if (fakeid_fd == -1 || fstat(fakeid_fd, &sb) == -1 || @@ -675,14 +675,32 @@ printit: /* Finally, we make and send the reply. */ - if (asprintf(&p, "%d , %d : USERID : %s : %s\r\n", lport, fport, osname, - idbuf) == -1) { + ssize = asprintf(&p, "%d , %d : USERID : %s : %s\r\n", lport, fport, + osname, idbuf); + if (p == NULL) { syslog(LOG_ERR, "asprintf: %m"); exit(EX_OSERR); } - send(s, p, strlen(p), MSG_EOF); + if (lflag) + syslog(LOG_INFO, "auth: %.*s (really %s)", + ssize - 2, p, pw ? pw->pw_name : "???"); + send(s, p, ssize, MSG_EOF); free(p); - + + exit(0); + +printerror: + ssize = asprintf(&p, "%d , %d : ERROR : %s\r\n", lport, fport, error); + if (p == NULL) { + syslog(LOG_ERR, "asprintf: %m"); + exit(EX_OSERR); + } + if (lflag) + syslog(LOG_INFO, "auth: %.*s (user %s)", + ssize - 2, p, pw ? pw->pw_name : "???"); + send(s, p, ssize, MSG_EOF); + free(p); + exit(0); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message