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