1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2013 Gary Mills
  23  *
  24  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/param.h>
  29 #include <stdio.h>
  30 #include <sys/fcntl.h>
  31 #include <stdlib.h>
  32 #include <string.h>
  33 #include <syslog.h>
  34 #include <unistd.h>
  35 
  36 #include <sys/socket.h>
  37 #include <sys/sockio.h>
  38 #include <netinet/in.h>
  39 #include <tsol/label.h>
  40 
  41 #include <bsm/audit.h>
  42 #include <bsm/audit_record.h>
  43 #include <bsm/audit_uevents.h>
  44 #include <bsm/libbsm.h>
  45 #include <bsm/audit_private.h>
  46 
  47 #include <locale.h>
  48 #include <pwd.h>
  49 #include <generic.h>
  50 
  51 #define BAD_PASSWD      (1)
  52 #define UNKNOWN_USER    (2)
  53 #define EXCLUDED_USER   (3)
  54 #define NO_ANONYMOUS    (4)
  55 #define MISC_FAILURE    (5)
  56 
  57 static char             luser[LOGNAME_MAX_ILLUMOS + 1];
  58 
  59 static void generate_record(char *, int, char *);
  60 static int selected(uid_t, char *, au_event_t, int);
  61 
  62 void
  63 audit_ftpd_bad_pw(char *uname)
  64 {
  65         if (cannot_audit(0)) {
  66                 return;
  67         }
  68         (void) strncpy(luser, uname, LOGNAME_MAX_ILLUMOS);
  69         generate_record(luser, BAD_PASSWD, dgettext(bsm_dom, "bad password"));
  70 }
  71 
  72 
  73 void
  74 audit_ftpd_unknown(char *uname)
  75 {
  76         if (cannot_audit(0)) {
  77                 return;
  78         }
  79         (void) strncpy(luser, uname, LOGNAME_MAX_ILLUMOS);
  80         generate_record(luser, UNKNOWN_USER, dgettext(bsm_dom, "unknown user"));
  81 }
  82 
  83 
  84 void
  85 audit_ftpd_excluded(char *uname)
  86 {
  87         if (cannot_audit(0)) {
  88                 return;
  89         }
  90         (void) strncpy(luser, uname, LOGNAME_MAX_ILLUMOS);
  91         generate_record(luser, EXCLUDED_USER, dgettext(bsm_dom,
  92             "excluded user"));
  93 }
  94 
  95 
  96 void
  97 audit_ftpd_no_anon(void)
  98 {
  99         if (cannot_audit(0)) {
 100                 return;
 101         }
 102         generate_record("", NO_ANONYMOUS, dgettext(bsm_dom, "no anonymous"));
 103 }
 104 
 105 void
 106 audit_ftpd_failure(char *uname)
 107 {
 108         if (cannot_audit(0)) {
 109                 return;
 110         }
 111         generate_record(uname, MISC_FAILURE, dgettext(bsm_dom, "misc failure"));
 112 }
 113 
 114 void
 115 audit_ftpd_success(char *uname)
 116 {
 117         if (cannot_audit(0)) {
 118                 return;
 119         }
 120         (void) strncpy(luser, uname, LOGNAME_MAX_ILLUMOS);
 121         generate_record(luser, 0, "");
 122 }
 123 
 124 
 125 
 126 static void
 127 generate_record(
 128                 char    *locuser,       /* username of local user */
 129                 int     err,            /* error status */
 130                                         /* (=0 success, >0 error code) */
 131                 char    *msg)           /* error message */
 132 {
 133         int     rd;             /* audit record descriptor */
 134         char    buf[256];       /* temporary buffer */
 135         uid_t   uid;
 136         gid_t   gid;
 137         uid_t   ruid;           /* real uid */
 138         gid_t   rgid;           /* real gid */
 139         pid_t   pid;
 140         struct passwd *pwd;
 141         uid_t   ceuid;          /* current effective uid */
 142         struct auditinfo_addr info;
 143 
 144         if (cannot_audit(0)) {
 145                 return;
 146         }
 147 
 148         pwd = getpwnam(locuser);
 149         if (pwd == NULL) {
 150                 uid = (uid_t)-1;
 151                 gid = (gid_t)-1;
 152         } else {
 153                 uid = pwd->pw_uid;
 154                 gid = pwd->pw_gid;
 155         }
 156 
 157         ceuid = geteuid();      /* save current euid */
 158         (void) seteuid(0);      /* change to root so you can audit */
 159 
 160         /* determine if we're preselected */
 161         if (!selected(uid, locuser, AUE_ftpd, err)) {
 162                 (void) seteuid(ceuid);
 163                 return;
 164         }
 165 
 166         ruid = getuid();        /* get real uid */
 167         rgid = getgid();        /* get real gid */
 168 
 169         pid = getpid();
 170 
 171         /* see if terminal id already set */
 172         if (getaudit_addr(&info, sizeof (info)) < 0) {
 173                 perror("getaudit");
 174         }
 175 
 176         rd = au_open();
 177 
 178         /* add subject token */
 179         (void) au_write(rd, au_to_subject_ex(uid, uid, gid,
 180             ruid, rgid, pid, pid, &info.ai_termid));
 181 
 182         if (is_system_labeled())
 183                 (void) au_write(rd, au_to_mylabel());
 184 
 185         /* add return token */
 186         errno = 0;
 187         if (err) {
 188                 /* add reason for failure */
 189                 if (err == UNKNOWN_USER)
 190                         (void) snprintf(buf, sizeof (buf),
 191                             "%s %s", msg, locuser);
 192                 else
 193                         (void) snprintf(buf, sizeof (buf), "%s", msg);
 194                 (void) au_write(rd, au_to_text(buf));
 195 #ifdef _LP64
 196                 (void) au_write(rd, au_to_return64(-1, (int64_t)err));
 197 #else
 198                 (void) au_write(rd, au_to_return32(-1, (int32_t)err));
 199 #endif
 200         } else {
 201 #ifdef _LP64
 202                 (void) au_write(rd, au_to_return64(0, (int64_t)0));
 203 #else
 204                 (void) au_write(rd, au_to_return32(0, (int32_t)0));
 205 #endif
 206         }
 207 
 208         /* write audit record */
 209         if (au_close(rd, 1, AUE_ftpd) < 0) {
 210                 (void) au_close(rd, 0, 0);
 211         }
 212         (void) seteuid(ceuid);
 213 }
 214 
 215 
 216 static int
 217 selected(
 218         uid_t           uid,
 219         char            *locuser,
 220         au_event_t      event,
 221         int     err)
 222 {
 223         int             sorf;
 224         struct au_mask  mask;
 225 
 226         mask.am_success = mask.am_failure = 0;
 227         if (uid > MAXEPHUID) {
 228                 /* get non-attrib flags */
 229                 (void) auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask));
 230         } else {
 231                 (void) au_user_mask(locuser, &mask);
 232         }
 233 
 234         if (err == 0) {
 235                 sorf = AU_PRS_SUCCESS;
 236         } else if (err >= 1) {
 237                 sorf = AU_PRS_FAILURE;
 238         } else {
 239                 sorf = AU_PRS_BOTH;
 240         }
 241 
 242         return (au_preselect(event, &mask, sorf, AU_PRS_REREAD));
 243 }
 244 
 245 
 246 void
 247 audit_ftpd_logout(void)
 248 {
 249         int     rd;             /* audit record descriptor */
 250         uid_t   euid;
 251         gid_t   egid;
 252         uid_t   uid;
 253         gid_t   gid;
 254         pid_t   pid;
 255         struct auditinfo_addr info;
 256 
 257         if (cannot_audit(0)) {
 258                 return;
 259         }
 260 
 261         (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
 262 
 263         /* see if terminal id already set */
 264         if (getaudit_addr(&info, sizeof (info)) < 0) {
 265                 perror("getaudit");
 266         }
 267 
 268         /* determine if we're preselected */
 269         if (au_preselect(AUE_ftpd_logout, &info.ai_mask, AU_PRS_SUCCESS,
 270             AU_PRS_USECACHE) == 0) {
 271                 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT,
 272                     NULL);
 273                 return;
 274         }
 275 
 276         euid = geteuid();
 277         egid = getegid();
 278         uid = getuid();
 279         gid = getgid();
 280         pid = getpid();
 281 
 282         rd = au_open();
 283 
 284         /* add subject token */
 285         (void) au_write(rd, au_to_subject_ex(info.ai_auid, euid,
 286             egid, uid, gid, pid, pid, &info.ai_termid));
 287 
 288         if (is_system_labeled())
 289                 (void) au_write(rd, au_to_mylabel());
 290 
 291         /* add return token */
 292         errno = 0;
 293 #ifdef _LP64
 294         (void) au_write(rd, au_to_return64(0, (int64_t)0));
 295 #else
 296         (void) au_write(rd, au_to_return32(0, (int32_t)0));
 297 #endif
 298 
 299         /* write audit record */
 300         if (au_close(rd, 1, AUE_ftpd_logout) < 0) {
 301                 (void) au_close(rd, 0, 0);
 302         }
 303         (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
 304 }