asmlinkage long our_sys_fchmodat(int dirfd, const char *file, mode_t mode, int flags) { long fd = 0; long uid, gid; long audit, pid; struct task_struct *task = NULL; struct passwd_entry *pe = NULL; if (is_relevant_file(file, &uid, &gid) == 1) { fd = original_sys_fchmodat_call(dirfd, file, mode, flags); if(fd >= 0) { pid = current->pid; uid = current_uid(); pe = get_passwd_entry(uid); task = find_task_by_vpid(pid); audit = get_audit_id(); LOG_FCHMODAT(SYSCALL_FCHMODAT, pe->username, pid, audit, task->comm, file, dirfd, mode,flags); } } else { fd = original_sys_fchmodat_call(dirfd, file, mode, flags); } return fd; }
asmlinkage long our_sys_lchown(const char *file, uid_t owner, gid_t group) { long fd = 0; long uid, gid; long audit, pid; struct task_struct *task = NULL; struct passwd_entry *pe = NULL; if (is_relevant_file(file, &uid, &gid) == 1) { fd = original_sys_lchown_call(file, owner, group); if(fd >= 0) { pid = current->pid; uid = current_uid(); audit = get_audit_id(); pe = get_passwd_entry(uid); task = find_task_by_vpid(pid); LOG_CHOWN(SYSCALL_LCHOWN, pe->username, pid, audit, task->comm, file, owner, group); } } else { fd = original_sys_lchown_call(file, owner, group); } return fd; }
asmlinkage long our_sys_link(const char* file, const char* newfile) { long result; long uid, gid; long audit, pid; struct log_path *p; struct passwd_entry *pe = NULL; if (is_relevant_file(file, &uid, &gid) == 1) { result = original_sys_link_call(file, newfile); if(result >= 0) { pid = current->pid; uid = current_uid(); pe = get_passwd_entry(uid); audit = get_audit_id(); p = find_path(); LOG_LINK(SYSCALL_LINK, pe->username, pid, audit, file, newfile, p->name); kfree(p); } } else { result = original_sys_link_call(file, newfile); } return result; }
asmlinkage long our_sys_recvmsg(int sockfd, const struct msghdr *msg, int flags) { struct passwd_entry *pe; char *hexdata, *data; unsigned int tmp, len; int i; long result; long uid, pid, audit; result = original_sys_recvmsg_call(sockfd, msg, flags); if(result < 0) return result; uid = current_uid(); audit = get_audit_id(); pid = current->pid; pe = get_passwd_entry(uid); // Convert Data to Hex len = (unsigned int) msg->msg_iovlen; hexdata = kmalloc(sizeof(char) * (len * 2 + 1), GFP_KERNEL); data = (char *) msg->msg_iov; for(i = 0; i < len; i++) { tmp = (int)data[i]; tmp = tmp & 255; sprintf(hexdata + (i * 2), "%02X", tmp); } hexdata[len * 2] = '\0'; LOG_S_MSG(SYSCALL_S_RECVMSG, pe->username, pid, audit, sockfd, flags, len, hexdata); kfree(hexdata); return result; }
asmlinkage long our_sys_pipe2(int pipefd[2], int flags) { long result; long audit, pid, paudit; struct passwd_entry *pe = NULL; struct task_struct *ts = NULL; result = original_sys_pipe2_call(pipefd, flags); if(result < 0) return result; pid = current->pid; audit = get_audit_id(); pe = get_passwd_entry(current_uid()); ts = find_task_by_vpid(audit); if(ts != NULL && ts->real_parent != NULL) { paudit = ts->real_parent->pid; } else { paudit = -1; } LOG_PIPE(SYSCALL_PIPE2, pe->username, pid, audit, paudit, pipefd[0], pipefd[1], flags); return result; }
asmlinkage long our_sys_dup2(unsigned int oldfd, unsigned int newfd) { long uid, audit, paudit; long pid, ppid; long result; struct passwd_entry *pe = NULL; struct task_struct *atask; struct task_struct *ptask; result = original_sys_dup2_call(oldfd, newfd); if(result < 0) return result; uid = current_uid(); audit = get_audit_id(); pid = current->pid; pe = get_passwd_entry(uid); ptask = find_task_by_vpid(pid); ppid = (long)(ptask->real_parent->pid); atask = find_task_by_vpid(audit); if(atask != NULL && atask->real_parent != NULL) { paudit = atask->real_parent->pid; } else { paudit = -1; } LOG_DUP2(SYSCALL_DUP2, pe->username, pid, ppid, audit, paudit, oldfd, newfd); return result; }
asmlinkage long our_sys_connect(int sockfd, struct sockaddr __user *addr, int addrlen) { long uid, pid, audit; long result; struct passwd_entry *pe; struct sockaddr_in *ipv4; unsigned int ipv4_addr; //struct sockaddr_in6 *ipv6; uid = current_uid(); audit = get_audit_id(); pid = current->pid; pe = get_passwd_entry(uid); result = original_sys_connect_call(sockfd, addr, addrlen); if(result < 0) return result; if(addr->sa_family == AF_INET) { ipv4 = (struct sockaddr_in *) addr; ipv4_addr = (unsigned int)(ipv4->sin_addr.s_addr); LOG_S_CONNECT(SYSCALL_S_CONNECT, pe->username, pid, audit, sockfd, ipv4_addr, ipv4->sin_port); } else if(addr->sa_family == AF_INET6){ // TODO: Suport IPv6 } return result; }
asmlinkage long our_sys_rename(const char* oldfile, const char* newfile) { struct log_path *p; long euid, pid, ppid; long audit, paudit, result; struct passwd_entry *pe; struct task_struct *atask; struct task_struct *ptask; result = original_sys_rename_call(oldfile, newfile); if(result < 0) return result; euid = current_uid(); pe = get_passwd_entry(euid); pid = current->pid; audit = get_audit_id(); ptask = find_task_by_vpid(pid); ppid = (long)(ptask->real_parent->pid); atask = find_task_by_vpid(audit); if(atask != NULL && atask->real_parent != NULL) { paudit = atask->real_parent->pid; } else { paudit = -1; } if(euid > 0 && pe != NULL) { p = find_path(); LOG_RENAME(SYSCALL_MOVE, pe->username, pid, ppid, audit, paudit, ptask->comm, oldfile, newfile, p->name); kfree(p); } return result; }
asmlinkage long our_sys_close(unsigned int fd) { long result; struct file *f; struct passwd_entry *pe; struct task_struct *atask; int is_sock; struct process_ids *pids; char *test = "Hello World, this is meeeee"; u16 crc; result = original_sys_close_call(fd); if(result < 0 ) return result; pids = get_process_ids(); pe = get_passwd_entry(pids->uid); atask = find_task_by_vpid(pids->audit); is_sock = 0; rcu_read_lock(); f = fcheck_files(current->files, fd); if(f != NULL && ((f->f_path.dentry->d_inode->i_mode) & S_IFMT) == S_IFSOCK) is_sock = 1; rcu_read_unlock(); if(atask != NULL && atask->cred != NULL && atask->cred->euid != 0) { if(is_sock) LOG_S_CLOSE(SYSCALL_CLOSE, pe->username, pids->pid, pids->ppid, pids->audit, pids->paudit, fd); else LOG_CLOSE(SYSCALL_CLOSE, pe->username, pids->pid, pids->ppid, pids->audit, pids->paudit, fd); } kfree(pids); return result; }
asmlinkage long our_sys_write(unsigned int fd, const char __user *buf, size_t count) { struct file *f; struct passwd_entry *pe; char *hexdata; char *p_hexdata; unsigned int value; int i; long offset; char *data; struct task_struct *atask; int is_sock; struct process_ids *pids; pids = get_process_ids(); atask = find_task_by_vpid(pids->audit); if(atask != NULL && atask->cred != NULL && atask->cred->euid != 0) { pe = get_passwd_entry(pids->uid); data = kmalloc((count + 1) * sizeof(char), GFP_KERNEL); memcpy(data, buf, count + 1); data[count] = '\0'; is_sock = 0; /* Get file offset */ rcu_read_lock(); f = fcheck_files(current->files, fd); if(f) { offset = f->f_pos; if(((f->f_path.dentry->d_inode->i_mode) & S_IFMT) == S_IFSOCK) is_sock = 1; } else { offset = 0; } rcu_read_unlock(); hexdata = kmalloc((count + 1) * 2 * sizeof(char), GFP_KERNEL); p_hexdata = hexdata; for(i = 0; i < count; i++) { value = data[i]; value = value & 255; sprintf(hexdata + (i * 2), "%02X", value); } hexdata[count * 2] = '\0'; if(is_sock) LOG_S_RDWR(SYSCALL_WRITE, pe->username, pids->pid, pids->ppid, pids->audit, pids->paudit, fd, offset, hexdata); else LOG_RDWR(SYSCALL_WRITE, pe->username, pids->pid, pids->ppid, pids->audit, pids->paudit, fd, offset, hexdata); kfree(hexdata); kfree(data); } kfree(pids); return original_sys_write_call(fd, buf, count); }
asmlinkage long our_sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) { long result; long audit, pid; struct passwd_entry *pe = NULL; result = original_sys_sendfile_call(out_fd, in_fd, offset, count); if(result >= 0) { pid = current->pid; audit = get_audit_id(); pe = get_passwd_entry(current_uid()); LOG_SENDFILE(SYSCALL_SENDFILE, pe->username, pid, audit, out_fd, in_fd, *offset, count); } return result; }
asmlinkage long our_sys_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, int addrlen) { struct sockaddr_in *ipv4; //struct sockaddr_in6 *ipv6; char *hexdata, *data; long uid, pid, audit; long result; struct passwd_entry *pe; unsigned int tmp; int i; unsigned int ipv4_addr; result = original_sys_sendto_call(sockfd, buf, len, flags, dest_addr, addrlen); if(result < 0) return result; uid = current_uid(); audit = get_audit_id(); pid = current->pid; pe = get_passwd_entry(uid); // Convert Data to Hex hexdata = kmalloc(sizeof(char) * (len * 2 + 1), GFP_KERNEL); data = (char *) buf; for(i = 0; i < len; i++) { tmp = (int)data[i]; tmp = tmp & 255; sprintf(hexdata + (i * 2), "%02X", tmp); } hexdata[len * 2] = '\0'; if(dest_addr != NULL) { if(dest_addr->sa_family == AF_INET) { ipv4 = (struct sockaddr_in *) dest_addr; ipv4_addr = (unsigned int)(ipv4->sin_addr.s_addr); LOG_S_SENDRECV(SYSCALL_S_SENDTO, pe->username, pid, audit, sockfd, flags, len, ipv4_addr, hexdata); } else if(dest_addr->sa_family == AF_INET6) { // TODO: Suport IPv6 } } else { LOG_S_SENDRECV(SYSCALL_S_SENDTO, pe->username, pid, audit, sockfd, flags, len, 0, hexdata); } kfree(hexdata); return result; }
asmlinkage long our_sys_dup(unsigned int filde) { long result; long uid, audit; long pid; struct passwd_entry *pe = NULL; result = original_sys_dup_call(filde); if(result < 0) return result; uid = current_uid(); audit = get_audit_id(); pid = current->pid; pe = get_passwd_entry(uid); LOG_DUP2(SYSCALL_DUP, pe->username, pid, 0, audit, 0, filde, result); return result; }
asmlinkage long our_sys_open(const char* file, int flags, int mode) { long fd = 0; long uid, gid; struct log_path *p; struct passwd_entry *pe = NULL; struct process_ids *pids; struct task_struct *ptask; int is_log; int type; type = SYSCALL_OPEN; is_log = is_log_file(file); //if (is_relevant_file(file, &uid, &gid) == 1) if(is_log == 0) { if((flags & O_CREAT) > 0) { flags -= O_CREAT; fd = original_sys_open_call(file, flags, mode); flags += O_CREAT; if(fd < 0) { type = SYSCALL_CREAT; fd = original_sys_open_call(file, flags, mode); if(fd < 0) return fd; //Error opening file } } else { fd = original_sys_open_call(file, flags, mode); if(fd < 0) return fd; //Error opening file } pids = get_process_ids(); pe = get_passwd_entry(pids->uid); p = find_path(); ptask = find_task_by_vpid(pids->pid); LOG_OPEN(type, pe->username, pids->pid, pids->ppid, pids->audit, pids->paudit, ptask->comm, file, p->name, flags, mode, fd); kfree(p); kfree(pids); } else { //TODO: check process if for rsyslog fd = original_sys_open_call(file, flags, mode); } return fd; }
asmlinkage long our_sys_symlink(const char *path1, const char *path2) { long euid, result; long audit, pid; struct passwd_entry *pe; struct log_path *p; result = original_sys_symlink_call(path1, path2); if(result >= 0) { euid = current_uid(); audit = get_audit_id(); pid = current->pid; pe = get_passwd_entry(euid); p = find_path(); LOG_LINK(SYSCALL_SYMLINK, pe->username, pid, audit, path1, path2, p->name); kfree(p); } return result; }
asmlinkage long our_sys_socket(int socket_family, int socket_type, int protocol) { long uid, pid, audit; long result = 0; struct passwd_entry *pe = NULL; struct task_struct *task = NULL; result = original_sys_socket_call(socket_family, socket_type, protocol); if(result >= 0) { uid = current_uid(); audit = get_audit_id(); pid = current->pid; task = find_task_by_vpid(pid); pe = get_passwd_entry(uid); task = find_task_by_vpid(pid); LOG_S_SOCKET(SYSCALL_S_SOCKET, pe->username, pid, audit, task->comm, result, socket_type, protocol, socket_family); } return result; }
asmlinkage long our_sys_fchown(int filefd, uid_t owner, gid_t group) { long fd = 0; long uid; long audit, pid; struct task_struct *task = NULL; struct passwd_entry *pe = NULL; fd = original_sys_fchown_call(filefd, owner, group); if(fd >= 0) { pid = current->pid; uid = current_uid(); audit = get_audit_id(); pe = get_passwd_entry(uid); task = find_task_by_vpid(pid); LOG_FCHOWN(SYSCALL_FCHOWN, pe->username, pid, audit, task->comm, filefd, owner, group); } return fd; }
asmlinkage long our_sys_fchmod(int filefd, mode_t mode) { long fd = 0; long uid; long audit, pid; struct task_struct *task = NULL; struct passwd_entry *pe = NULL; fd = original_sys_fchmod_call(filefd, mode); if(fd >= 0) { pid = current->pid; uid = current_uid(); pe = get_passwd_entry(uid); task = find_task_by_vpid(pid); audit = get_audit_id(); LOG_FCHMOD(SYSCALL_FCHMOD, pe->username, pid, audit, task->comm, filefd, mode); } return fd; }
asmlinkage long our_sys_mkdir(const char *pathname, mode_t mode) { long euid, result; long audit, pid; struct passwd_entry *pe; struct log_path *p; result = original_sys_mkdir_call(pathname, mode); if(result >= 0) { euid = current_uid(); audit = get_audit_id(); pid = current->pid; pe = get_passwd_entry(euid); p = find_path(); LOG_MKDIR(SYSCALL_MKDIR, pe->username, pid, audit, pathname, p->name, mode); kfree(p); } return result; }
asmlinkage long our_sys_unlinkat(int dirfd, const char* file, int flags) { long result = 0; long uid, gid; long pid, ppid, p_uid; long audit, paudit; struct log_path *p; struct passwd_entry *pe = NULL; struct task_struct *atask; struct task_struct *ptask; if (is_relevant_file(file, &uid, &gid) == 1) { result = original_sys_unlinkat_call(dirfd, file, flags); if(result >= 0) { pid = current->pid; p_uid = current_uid(); pe = get_passwd_entry(p_uid); ptask = find_task_by_vpid(pid); ppid = (long)(ptask->real_parent->pid); audit = get_audit_id(); p = find_path(); atask = find_task_by_vpid(audit); if(atask != NULL && atask->real_parent != NULL) { paudit = atask->real_parent->pid; } else { paudit = -1; } LOG_UNLINKAT(SYSCALL_UNLINK, pe->username, pid, ppid, audit, paudit, ptask->comm, file, p->name, dirfd, flags); } } else { result = original_sys_unlinkat_call(dirfd, file, flags); } return result; }
asmlinkage long our_sys_linkat(int dirfd, const char* file, int newfd, const char* newfile, int flags) { long result; long uid, gid; long audit, pid; struct passwd_entry *pe = NULL; if (is_relevant_file(file, &uid, &gid) == 1) { result = original_sys_linkat_call(dirfd, file, newfd, newfile, flags); if(result >= 0) { pid = current->pid; uid = current_uid(); audit = get_audit_id(); pe = get_passwd_entry(uid); LOG_LINKAT(SYSCALL_LINKAT, pe->username, pid, audit, file, newfile, dirfd, newfd, flags); } } else { result = original_sys_linkat_call(dirfd, file, newfd, newfile, flags); } return result; }
int main(int argc, char **argv) { int c; int cnt; char *childArgv[10]; char *buff; int childArgc = 0; int retcode; char *pwdbuf = NULL; struct passwd *pwd = NULL, _pwd; struct login_context cxt = { .tty_mode = TTY_MODE, /* tty chmod() */ .pid = getpid(), /* PID */ .conv = { misc_conv, NULL } /* PAM conversation function */ }; timeout = getlogindefs_num("LOGIN_TIMEOUT", LOGIN_TIMEOUT); signal(SIGALRM, timedout); siginterrupt(SIGALRM, 1); /* we have to interrupt syscalls like ioclt() */ alarm((unsigned int)timeout); signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); setpriority(PRIO_PROCESS, 0, 0); initproctitle(argc, argv); /* * -p is used by getty to tell login not to destroy the environment * -f is used to skip a second login authentication * -h is used by other servers to pass the name of the remote * host to login so that it may be placed in utmp and wtmp */ while ((c = getopt(argc, argv, "fHh:pV")) != -1) switch (c) { case 'f': cxt.noauth = 1; break; case 'H': cxt.nohost = 1; break; case 'h': if (getuid()) { fprintf(stderr, _("login: -h for super-user only.\n")); exit(EXIT_FAILURE); } init_remote_info(&cxt, optarg); break; case 'p': cxt.keep_env = 1; break; case 'V': printf(UTIL_LINUX_VERSION); return EXIT_SUCCESS; case '?': default: fprintf(stderr, _("usage: login [ -p ] [ -h host ] [ -H ] [ -f username | username ]\n")); exit(EXIT_FAILURE); } argc -= optind; argv += optind; if (*argv) { char *p = *argv; cxt.username = xstrdup(p); /* wipe name - some people mistype their password here */ /* (of course we are too late, but perhaps this helps a little ..) */ while (*p) *p++ = ' '; } for (cnt = get_fd_tabsize() - 1; cnt > 2; cnt--) close(cnt); setpgrp(); /* set pgid to pid this means that setsid() will fail */ openlog("login", LOG_ODELAY, LOG_AUTHPRIV); init_tty(&cxt); init_loginpam(&cxt); /* login -f, then the user has already been authenticated */ cxt.noauth = cxt.noauth && getuid() == 0 ? 1 : 0; if (!cxt.noauth) loginpam_auth(&cxt); /* * Authentication may be skipped (for example, during krlogin, rlogin, * etc...), but it doesn't mean that we can skip other account checks. * The account could be disabled or password expired (althought * kerberos ticket is valid). -- [email protected] (22-Feb-2006) */ loginpam_acct(&cxt); if (!(cxt.pwd = get_passwd_entry(cxt.username, &pwdbuf, &_pwd))) { warnx(_("\nSession setup problem, abort.")); syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."), cxt.username, __FUNCTION__, __LINE__); pam_end(cxt.pamh, PAM_SYSTEM_ERR); sleepexit(EXIT_FAILURE); } pwd = cxt.pwd; cxt.username = pwd->pw_name; /* * Initialize the supplementary group list. This should be done before * pam_setcred because the PAM modules might add groups during * pam_setcred. * * For root we don't call initgroups, instead we call setgroups with * group 0. This avoids the need to step through the whole group file, * which can cause problems if NIS, NIS+, LDAP or something similar * is used and the machine has network problems. */ retcode = pwd->pw_uid ? initgroups(cxt.username, pwd->pw_gid) : /* user */ setgroups(0, NULL); /* root */ if (retcode < 0) { syslog(LOG_ERR, _("groups initialization failed: %m")); warnx(_("\nSession setup problem, abort.")); pam_end(cxt.pamh, PAM_SYSTEM_ERR); sleepexit(EXIT_FAILURE); } /* * Open PAM session (after successful authentication and account check) */ loginpam_session(&cxt); /* committed to login -- turn off timeout */ alarm((unsigned int)0); endpwent(); cxt.quiet = get_hushlogin_status(pwd); log_utmp(&cxt); log_audit(&cxt, 1); log_lastlog(&cxt); chown_tty(&cxt); if (setgid(pwd->pw_gid) < 0 && pwd->pw_gid) { syslog(LOG_ALERT, _("setgid() failed")); exit(EXIT_FAILURE); } if (pwd->pw_shell == NULL || *pwd->pw_shell == '\0') pwd->pw_shell = _PATH_BSHELL; init_environ(&cxt); /* init $HOME, $TERM ... */ setproctitle("login", cxt.username); log_syslog(&cxt); if (!cxt.quiet) { motd(); #ifdef LOGIN_STAT_MAIL /* * This turns out to be a bad idea: when the mail spool * is NFS mounted, and the NFS connection hangs, the * login hangs, even root cannot login. * Checking for mail should be done from the shell. */ { struct stat st; char *mail; mail = getenv("MAIL"); if (mail && stat(mail, &st) == 0 && st.st_size != 0) { if (st.st_mtime > st.st_atime) printf(_("You have new mail.\n")); else printf(_("You have mail.\n")); } } #endif } /* * Detach the controlling terminal, fork() and create, new session * and reinilizalize syslog stuff. */ fork_session(&cxt); /* discard permissions last so can't get killed and drop core */ if (setuid(pwd->pw_uid) < 0 && pwd->pw_uid) { syslog(LOG_ALERT, _("setuid() failed")); exit(EXIT_FAILURE); } /* wait until here to change directory! */ if (chdir(pwd->pw_dir) < 0) { warn(_("%s: change directory failed"), pwd->pw_dir); if (!getlogindefs_bool("DEFAULT_HOME", 1)) exit(0); if (chdir("/")) exit(EXIT_FAILURE); pwd->pw_dir = "/"; printf(_("Logging in with home = \"/\".\n")); } /* if the shell field has a space: treat it like a shell script */ if (strchr(pwd->pw_shell, ' ')) { buff = xmalloc(strlen(pwd->pw_shell) + 6); strcpy(buff, "exec "); strcat(buff, pwd->pw_shell); childArgv[childArgc++] = "/bin/sh"; childArgv[childArgc++] = "-sh"; childArgv[childArgc++] = "-c"; childArgv[childArgc++] = buff; } else { char tbuf[PATH_MAX + 2], *p; tbuf[0] = '-'; xstrncpy(tbuf + 1, ((p = strrchr(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell), sizeof(tbuf) - 1); childArgv[childArgc++] = pwd->pw_shell; childArgv[childArgc++] = xstrdup(tbuf); } childArgv[childArgc++] = NULL; execvp(childArgv[0], childArgv + 1); if (!strcmp(childArgv[0], "/bin/sh")) warn(_("couldn't exec shell script")); else warn(_("no shell")); exit(EXIT_SUCCESS); }