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 #ifdef  LOGNAME_MAX_ILLUMOS
  58 #define _LOGNAME_MAX    LOGNAME_MAX_ILLUMOS
  59 #else /* LOGNAME_MAX_ILLUMOS */
  60 #define _LOGNAME_MAX    LOGNAME_MAX
  61 #endif /* LOGNAME_MAX_ILLUMOS */
  62 
  63 static char             luser[_LOGNAME_MAX + 1];
  64 
  65 static void generate_record(char *, int, char *);
  66 static int selected(uid_t, char *, au_event_t, int);
  67 
  68 void
  69 audit_ftpd_bad_pw(char *uname)
  70 {
  71         if (cannot_audit(0)) {
  72                 return;
  73         }
  74         (void) strncpy(luser, uname, _LOGNAME_MAX);
  75         generate_record(luser, BAD_PASSWD, dgettext(bsm_dom, "bad password"));
  76 }
  77 
  78 
  79 void
  80 audit_ftpd_unknown(char *uname)
  81 {
  82         if (cannot_audit(0)) {
  83                 return;
  84         }
  85         (void) strncpy(luser, uname, _LOGNAME_MAX);
  86         generate_record(luser, UNKNOWN_USER, dgettext(bsm_dom, "unknown user"));
  87 }
  88 
  89 
  90 void
  91 audit_ftpd_excluded(char *uname)
  92 {
  93         if (cannot_audit(0)) {
  94                 return;
  95         }
  96         (void) strncpy(luser, uname, _LOGNAME_MAX);
  97         generate_record(luser, EXCLUDED_USER, dgettext(bsm_dom,
  98             "excluded user"));
  99 }
 100 
 101 
 102 void
 103 audit_ftpd_no_anon(void)
 104 {
 105         if (cannot_audit(0)) {
 106                 return;
 107         }
 108         generate_record("", NO_ANONYMOUS, dgettext(bsm_dom, "no anonymous"));
 109 }
 110 
 111 void
 112 audit_ftpd_failure(char *uname)
 113 {
 114         if (cannot_audit(0)) {
 115                 return;
 116         }
 117         generate_record(uname, MISC_FAILURE, dgettext(bsm_dom, "misc failure"));
 118 }
 119 
 120 void
 121 audit_ftpd_success(char *uname)
 122 {
 123         if (cannot_audit(0)) {
 124                 return;
 125         }
 126         (void) strncpy(luser, uname, _LOGNAME_MAX);
 127         generate_record(luser, 0, "");
 128 }
 129 
 130 
 131 
 132 static void
 133 generate_record(
 134                 char    *locuser,       /* username of local user */
 135                 int     err,            /* error status */
 136                                         /* (=0 success, >0 error code) */
 137                 char    *msg)           /* error message */
 138 {
 139         int     rd;             /* audit record descriptor */
 140         char    buf[256];       /* temporary buffer */
 141         uid_t   uid;
 142         gid_t   gid;
 143         uid_t   ruid;           /* real uid */
 144         gid_t   rgid;           /* real gid */
 145         pid_t   pid;
 146         struct passwd *pwd;
 147         uid_t   ceuid;          /* current effective uid */
 148         struct auditinfo_addr info;
 149 
 150         if (cannot_audit(0)) {
 151                 return;
 152         }
 153 
 154         pwd = getpwnam(locuser);
 155         if (pwd == NULL) {
 156                 uid = (uid_t)-1;
 157                 gid = (gid_t)-1;
 158         } else {
 159                 uid = pwd->pw_uid;
 160                 gid = pwd->pw_gid;
 161         }
 162 
 163         ceuid = geteuid();      /* save current euid */
 164         (void) seteuid(0);      /* change to root so you can audit */
 165 
 166         /* determine if we're preselected */
 167         if (!selected(uid, locuser, AUE_ftpd, err)) {
 168                 (void) seteuid(ceuid);
 169                 return;
 170         }
 171 
 172         ruid = getuid();        /* get real uid */
 173         rgid = getgid();        /* get real gid */
 174 
 175         pid = getpid();
 176 
 177         /* see if terminal id already set */
 178         if (getaudit_addr(&info, sizeof (info)) < 0) {
 179                 perror("getaudit");
 180         }
 181 
 182         rd = au_open();
 183 
 184         /* add subject token */
 185         (void) au_write(rd, au_to_subject_ex(uid, uid, gid,
 186             ruid, rgid, pid, pid, &info.ai_termid));
 187 
 188         if (is_system_labeled())
 189                 (void) au_write(rd, au_to_mylabel());
 190 
 191         /* add return token */
 192         errno = 0;
 193         if (err) {
 194                 /* add reason for failure */
 195                 if (err == UNKNOWN_USER)
 196                         (void) snprintf(buf, sizeof (buf),
 197                             "%s %s", msg, locuser);
 198                 else
 199                         (void) snprintf(buf, sizeof (buf), "%s", msg);
 200                 (void) au_write(rd, au_to_text(buf));
 201 #ifdef _LP64
 202                 (void) au_write(rd, au_to_return64(-1, (int64_t)err));
 203 #else
 204                 (void) au_write(rd, au_to_return32(-1, (int32_t)err));
 205 #endif
 206         } else {
 207 #ifdef _LP64
 208                 (void) au_write(rd, au_to_return64(0, (int64_t)0));
 209 #else
 210                 (void) au_write(rd, au_to_return32(0, (int32_t)0));
 211 #endif
 212         }
 213 
 214         /* write audit record */
 215         if (au_close(rd, 1, AUE_ftpd) < 0) {
 216                 (void) au_close(rd, 0, 0);
 217         }
 218         (void) seteuid(ceuid);
 219 }
 220 
 221 
 222 static int
 223 selected(
 224         uid_t           uid,
 225         char            *locuser,
 226         au_event_t      event,
 227         int     err)
 228 {
 229         int             sorf;
 230         struct au_mask  mask;
 231 
 232         mask.am_success = mask.am_failure = 0;
 233         if (uid > MAXEPHUID) {
 234                 /* get non-attrib flags */
 235                 (void) auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask));
 236         } else {
 237                 (void) au_user_mask(locuser, &mask);
 238         }
 239 
 240         if (err == 0) {
 241                 sorf = AU_PRS_SUCCESS;
 242         } else if (err >= 1) {
 243                 sorf = AU_PRS_FAILURE;
 244         } else {
 245                 sorf = AU_PRS_BOTH;
 246         }
 247 
 248         return (au_preselect(event, &mask, sorf, AU_PRS_REREAD));
 249 }
 250 
 251 
 252 void
 253 audit_ftpd_logout(void)
 254 {
 255         int     rd;             /* audit record descriptor */
 256         uid_t   euid;
 257         gid_t   egid;
 258         uid_t   uid;
 259         gid_t   gid;
 260         pid_t   pid;
 261         struct auditinfo_addr info;
 262 
 263         if (cannot_audit(0)) {
 264                 return;
 265         }
 266 
 267         (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
 268 
 269         /* see if terminal id already set */
 270         if (getaudit_addr(&info, sizeof (info)) < 0) {
 271                 perror("getaudit");
 272         }
 273 
 274         /* determine if we're preselected */
 275         if (au_preselect(AUE_ftpd_logout, &info.ai_mask, AU_PRS_SUCCESS,
 276             AU_PRS_USECACHE) == 0) {
 277                 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT,
 278                     NULL);
 279                 return;
 280         }
 281 
 282         euid = geteuid();
 283         egid = getegid();
 284         uid = getuid();
 285         gid = getgid();
 286         pid = getpid();
 287 
 288         rd = au_open();
 289 
 290         /* add subject token */
 291         (void) au_write(rd, au_to_subject_ex(info.ai_auid, euid,
 292             egid, uid, gid, pid, pid, &info.ai_termid));
 293 
 294         if (is_system_labeled())
 295                 (void) au_write(rd, au_to_mylabel());
 296 
 297         /* add return token */
 298         errno = 0;
 299 #ifdef _LP64
 300         (void) au_write(rd, au_to_return64(0, (int64_t)0));
 301 #else
 302         (void) au_write(rd, au_to_return32(0, (int32_t)0));
 303 #endif
 304 
 305         /* write audit record */
 306         if (au_close(rd, 1, AUE_ftpd_logout) < 0) {
 307                 (void) au_close(rd, 0, 0);
 308         }
 309         (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
 310 }