/* * Policy: passwd. * * (c) 2002, 2003 Pawel Jakub Dawidek * * $Id: passwd.cb,v 1.30 2003/08/12 12:36:30 dawidek Exp $ */ #include "addons.cbh" #if CERB_VERSION < 2003032101 #error Newer CerbNG required for this policy. #endif #define PASSWD_PNAME "passwd" #define PASSWD_PATH "/usr/bin/passwd" #define PASSWD_INODE GET_INODE(PASSWD_PATH) #define PASSWD_DEV GET_DEV(PASSWD_PATH) #define PWD_MKDB_PATH "/usr/sbin/pwd_mkdb" #define PWD_MKDB_INODE GET_INODE(PWD_MKDB_PATH) #define PWD_MKDB_DEV GET_DEV(PWD_MKDB_PATH) #define PASSWD_VERBOSE 1 beginrules REGISTER("passwd"); #if CERB_VERSION >= 2003062901 if (INITRUN()) { crsysctl("passwd"); crsysctl("passwd.pname", PASSWD_PNAME, CTLFLAG_RD); crsysctl("passwd.path", PASSWD_PATH, CTLFLAG_RD); crsysctl("passwd.inode", PASSWD_INODE); #undef PASSWD_INODE #define PASSWD_INODE CB_SYSCTL("passwd.inode") crsysctl("passwd.dev", PASSWD_DEV); #undef PASSWD_DEV #define PASSWD_DEV CB_SYSCTL("passwd.dev") crsysctl("passwd.pwd_mkdb"); crsysctl("passwd.pwd_mkdb.path", PWD_MKDB_PATH, CTLFLAG_RD); crsysctl("passwd.pwd_mkdb.inode", PWD_MKDB_INODE); #undef PWD_MKDB_INODE #define PWD_MKDB_INODE CB_SYSCTL("passwd.pwd_mkdb.inode") crsysctl("passwd.pwd_mkdb.dev", PWD_MKDB_DEV); #undef PWD_MKDB_DEV #define PWD_MKDB_DEV CB_SYSCTL("passwd.pwd_mkdb.dev") crsysctl("passwd.verbose", PASSWD_VERBOSE); #undef PASSWD_VERBOSE #define PASSWD_VERBOSE CB_SYSCTL("passwd.verbose") } #endif ADD_SYSCALL( SYS_execve, SYS_open, SYS_unlink, SYS_setrlimit, SYS_open, SYS_rename ); if (syscall == SYS_execve && ruid > 0) { if (getinode(arg[0]) == PASSWD_INODE && getdev(arg[0]) == PASSWD_DEV) { reg[1] = call(); if (reg[1] != 0) { return reg[1]; } /* everything is correct, removing uid and gid 0 */ if (euid == 0) { CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Removed uid 0."); setpeuid(ruid); setpsvuid(ruid); } return 0; } } if (finode == PASSWD_INODE && fdev == PASSWD_DEV && ruid > 0) { if (syscall == SYS_execve) { /* we gives access to execute only pwd_mkdb */ reg[0] = getinode(arg[0]); reg[1] = getdev(arg[0]); if (arg[0] != "/usr/sbin/pwd_mkdb" || reg[0] != PWD_MKDB_INODE || reg[1] != PWD_MKDB_DEV) { CB_LOGEXT(PASSWD_VERBOSE, LOG_WARNING, "!!WARN!! " "Attempt to run %s (%s) (inode=%u:dev=%u).", arg[0], realpath(arg[0]), reg[0], reg[1]); return EPERM; } /* let's check arguments */ reg[2] = [ "pwd_mkdb", "-p", "-d", "/etc", "-u" ]; reg[2] = addelem(reg[2], login); reg[2] = addelem(reg[2], getelem(arg[1], 6)); if (arg[1] != reg[2]) { CB_LOGEXT(PASSWD_VERBOSE, LOG_WARNING, "!!WARN!! Wrong " "arguments."); return EPERM; } /* We have to remember name of program that will be called, because after execve() call arguments will be empty. */ reg[1] = arg[0]; /* now we set effective uid to 0 */ reg[0] = sucall(); /* calling execve() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Calling %s [ret=%d].", reg[1], reg[0]); return reg[0]; } if (syscall == SYS_open) { /* we got open flags in arg[1] and mode in arg[2] */ if (arg[1] == (O_CREAT | O_EXCL | O_RDWR) && arg[2] == 0600) { if (arg[0] @ "/etc/pw.??????") { reg[0] = sucall(); /* calling open() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Opening " "%s (flags=%o) " "[ret=%d].", arg[0], arg[1], reg[0]); return reg[0]; } } if (arg[1] == O_RDONLY) { /* * passwd want to check old password, * so euid = 0 again */ if (arg[0] == "/etc/spwd.db" || arg[0] == "/etc/master.passwd" || arg[0] == "/etc/login.conf.db") { reg[0] = sucall(); /* calling open() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Opening " "%s (flags=%o) " "[ret=%d].", arg[0], arg[1], reg[0]); return reg[0]; } } } if (syscall == SYS_unlink) { /* we can remove temporary files */ if (arg[0] @ "/etc/pw.??????") { reg[0] = sucall(); /* calling unlink() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Removing %s " "[ret=%d].", arg[0], reg[0]); return reg[0]; } } if (syscall == SYS_setrlimit) { reg[0] = sucall(); /* calling setrlimit() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Setting rlimit [ret=%d].", reg[0]); return reg[0]; } } if (finode == PWD_MKDB_INODE && fdev == PWD_MKDB_DEV && ruid > 0) { if (syscall == SYS_open) { if (arg[1] == O_RDONLY) { if (arg[0] == "/etc/spwd.db" || arg[0] @ "/etc/pw.??????") { reg[0] = sucall(); /* calling open() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Opening " "%s [ret=%d].", arg[0], reg[0]); return reg[0]; } } if (arg[1] == (O_CREAT | O_EXCL | O_WRONLY) || arg[1] == (O_EXCL | O_RDWR)) { if (arg[2] == 0644 && arg[0] == "/etc/pwd.db.tmp") { reg[0] = sucall(); /* calling open() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Opening " "%s [ret=%d].", arg[0], reg[0]); return reg[0]; } if (arg[2] == 0600 && arg[0] == "/etc/spwd.db.tmp") { reg[0] = sucall(); /* calling open() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Opening " "%s [ret=%d].", arg[0], reg[0]); return reg[0]; } } if (arg[1] == (O_CREAT | O_EXCL | O_WRONLY)) { if (arg[2] == 0644 && arg[0] @ "/etc/pw.??????.orig") { reg[0] = sucall(); /* calling open() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Opening " "%s [ret=%d].", arg[0], reg[0]); return reg[0]; } } } if (syscall == SYS_rename) { if ((arg[0] == "/etc/pwd.db.tmp" && arg[1] == "/etc/pwd.db") || (arg[0] == "/etc/spwd.db.tmp" && arg[1] == "/etc/spwd.db") || (arg[0] @ "/etc/pw.??????.orig" && arg[1] == "/etc/passwd") || (arg[0] @ "/etc/pw.??????" && arg[1] == "/etc/master.passwd")) { reg[0] = sucall(); /* calling open() */ CB_LOGEXT(PASSWD_VERBOSE, LOG_INFO, "Renaming %s to %s " "[ret=%d].", arg[0], arg[1], reg[0]); return reg[0]; } } } endrules