view usr/src/lib/libbsm/common/audit_ftpd.c @ 12930:32a41a5f8110

PSARC/2009/636 Obsolete getacinfo(3bsm) PSARC/2009/642 audit_control(4) EOL and removal PSARC/2010/218 Audit subsystem Rights Profiles PSARC/2010/220 svc:/system/auditset service 6875456 Solaris Audit configuration in SMF - phase 2 (PSARC/2009/636, PSARC/2009/642) 6942035 audit_binfile(5) leaves unfinished audit logs. 6942041 auditd(1) says "auditd refreshed" on startup. 6943275 audit_remote(5) leaks memory on audit service refresh 6955077 adt_get_mask_from_user() should regard _SC_GETPW_R_SIZE_MAX 6955117 $SRC/lib/libbsm/common/audit_ftpd.c shouldn't hardcode the lenght of usernames (8) 6956169 adt_audit_state() returns non-boolean values
author Jan Friedel <Jan.Friedel@Sun.COM>
date Tue, 27 Jul 2010 14:38:47 +0200
parents a8930ec16e52
children
line wrap: on
line source

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/sockio.h>
#include <netinet/in.h>
#include <tsol/label.h>

#include <bsm/audit.h>
#include <bsm/audit_record.h>
#include <bsm/audit_uevents.h>
#include <bsm/libbsm.h>
#include <bsm/audit_private.h>

#include <locale.h>
#include <pwd.h>
#include <generic.h>

#define	BAD_PASSWD	(1)
#define	UNKNOWN_USER	(2)
#define	EXCLUDED_USER	(3)
#define	NO_ANONYMOUS	(4)
#define	MISC_FAILURE	(5)

static char		luser[LOGNAME_MAX + 1];

static void generate_record(char *, int, char *);
static int selected(uid_t, char *, au_event_t, int);

void
audit_ftpd_bad_pw(char *uname)
{
	if (cannot_audit(0)) {
		return;
	}
	(void) strncpy(luser, uname, LOGNAME_MAX);
	generate_record(luser, BAD_PASSWD, dgettext(bsm_dom, "bad password"));
}


void
audit_ftpd_unknown(char	*uname)
{
	if (cannot_audit(0)) {
		return;
	}
	(void) strncpy(luser, uname, LOGNAME_MAX);
	generate_record(luser, UNKNOWN_USER, dgettext(bsm_dom, "unknown user"));
}


void
audit_ftpd_excluded(char *uname)
{
	if (cannot_audit(0)) {
		return;
	}
	(void) strncpy(luser, uname, LOGNAME_MAX);
	generate_record(luser, EXCLUDED_USER, dgettext(bsm_dom,
	    "excluded user"));
}


void
audit_ftpd_no_anon(void)
{
	if (cannot_audit(0)) {
		return;
	}
	generate_record("", NO_ANONYMOUS, dgettext(bsm_dom, "no anonymous"));
}

void
audit_ftpd_failure(char *uname)
{
	if (cannot_audit(0)) {
		return;
	}
	generate_record(uname, MISC_FAILURE, dgettext(bsm_dom, "misc failure"));
}

void
audit_ftpd_success(char	*uname)
{
	if (cannot_audit(0)) {
		return;
	}
	(void) strncpy(luser, uname, LOGNAME_MAX);
	generate_record(luser, 0, "");
}



static void
generate_record(
		char	*locuser,	/* username of local user */
		int	err,		/* error status */
					/* (=0 success, >0 error code) */
		char	*msg)		/* error message */
{
	int	rd;		/* audit record descriptor */
	char	buf[256];	/* temporary buffer */
	uid_t	uid;
	gid_t	gid;
	uid_t	ruid;		/* real uid */
	gid_t	rgid;		/* real gid */
	pid_t	pid;
	struct passwd *pwd;
	uid_t	ceuid;		/* current effective uid */
	struct auditinfo_addr info;

	if (cannot_audit(0)) {
		return;
	}

	pwd = getpwnam(locuser);
	if (pwd == NULL) {
		uid = (uid_t)-1;
		gid = (gid_t)-1;
	} else {
		uid = pwd->pw_uid;
		gid = pwd->pw_gid;
	}

	ceuid = geteuid();	/* save current euid */
	(void) seteuid(0);	/* change to root so you can audit */

	/* determine if we're preselected */
	if (!selected(uid, locuser, AUE_ftpd, err)) {
		(void) seteuid(ceuid);
		return;
	}

	ruid = getuid();	/* get real uid */
	rgid = getgid();	/* get real gid */

	pid = getpid();

	/* see if terminal id already set */
	if (getaudit_addr(&info, sizeof (info)) < 0) {
		perror("getaudit");
	}

	rd = au_open();

	/* add subject token */
	(void) au_write(rd, au_to_subject_ex(uid, uid, gid,
	    ruid, rgid, pid, pid, &info.ai_termid));

	if (is_system_labeled())
		(void) au_write(rd, au_to_mylabel());

	/* add return token */
	errno = 0;
	if (err) {
		/* add reason for failure */
		if (err == UNKNOWN_USER)
			(void) snprintf(buf, sizeof (buf),
			    "%s %s", msg, locuser);
		else
			(void) snprintf(buf, sizeof (buf), "%s", msg);
		(void) au_write(rd, au_to_text(buf));
#ifdef _LP64
		(void) au_write(rd, au_to_return64(-1, (int64_t)err));
#else
		(void) au_write(rd, au_to_return32(-1, (int32_t)err));
#endif
	} else {
#ifdef _LP64
		(void) au_write(rd, au_to_return64(0, (int64_t)0));
#else
		(void) au_write(rd, au_to_return32(0, (int32_t)0));
#endif
	}

	/* write audit record */
	if (au_close(rd, 1, AUE_ftpd) < 0) {
		(void) au_close(rd, 0, 0);
	}
	(void) seteuid(ceuid);
}


static int
selected(
	uid_t		uid,
	char		*locuser,
	au_event_t	event,
	int	err)
{
	int		sorf;
	struct au_mask	mask;

	mask.am_success = mask.am_failure = 0;
	if (uid > MAXEPHUID) {
		/* get non-attrib flags */
		(void) auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask));
	} else {
		(void) au_user_mask(locuser, &mask);
	}

	if (err == 0) {
		sorf = AU_PRS_SUCCESS;
	} else if (err >= 1) {
		sorf = AU_PRS_FAILURE;
	} else {
		sorf = AU_PRS_BOTH;
	}

	return (au_preselect(event, &mask, sorf, AU_PRS_REREAD));
}


void
audit_ftpd_logout(void)
{
	int	rd;		/* audit record descriptor */
	uid_t	euid;
	gid_t	egid;
	uid_t	uid;
	gid_t	gid;
	pid_t	pid;
	struct auditinfo_addr info;

	if (cannot_audit(0)) {
		return;
	}

	(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);

	/* see if terminal id already set */
	if (getaudit_addr(&info, sizeof (info)) < 0) {
		perror("getaudit");
	}

	/* determine if we're preselected */
	if (au_preselect(AUE_ftpd_logout, &info.ai_mask, AU_PRS_SUCCESS,
	    AU_PRS_USECACHE) == 0) {
		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT,
		    NULL);
		return;
	}

	euid = geteuid();
	egid = getegid();
	uid = getuid();
	gid = getgid();
	pid = getpid();

	rd = au_open();

	/* add subject token */
	(void) au_write(rd, au_to_subject_ex(info.ai_auid, euid,
	    egid, uid, gid, pid, pid, &info.ai_termid));

	if (is_system_labeled())
		(void) au_write(rd, au_to_mylabel());

	/* add return token */
	errno = 0;
#ifdef _LP64
	(void) au_write(rd, au_to_return64(0, (int64_t)0));
#else
	(void) au_write(rd, au_to_return32(0, (int32_t)0));
#endif

	/* write audit record */
	if (au_close(rd, 1, AUE_ftpd_logout) < 0) {
		(void) au_close(rd, 0, 0);
	}
	(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
}