2007-10-07 17:14:02 +05:30
|
|
|
/*
|
2008-04-27 06:10:09 +05:30
|
|
|
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
|
|
|
|
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
|
|
|
|
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
|
|
|
|
* Copyright (c) 2007 - 2008, Nicolas François
|
2007-10-07 17:14:02 +05:30
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2008-04-27 06:10:09 +05:30
|
|
|
* 3. The name of the copyright holders or contributors may not be used to
|
|
|
|
* endorse or promote products derived from this software without
|
|
|
|
* specific prior written permission.
|
2007-10-07 17:14:02 +05:30
|
|
|
*
|
2008-04-27 06:10:09 +05:30
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
|
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Separated from setup.c. --marekm
|
|
|
|
* Resource limits thanks to Cristian Gafton.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
#ifndef USE_PAM
|
|
|
|
|
2007-11-11 05:16:11 +05:30
|
|
|
#ident "$Id$"
|
2007-10-07 17:17:01 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "prototypes.h"
|
|
|
|
#include "defines.h"
|
|
|
|
#include <pwd.h>
|
|
|
|
#include "getdef.h"
|
|
|
|
#ifdef HAVE_SYS_RESOURCE_H
|
|
|
|
#include <sys/resource.h>
|
|
|
|
#define LIMITS
|
|
|
|
#endif
|
|
|
|
#ifdef LIMITS
|
|
|
|
#ifndef LIMITS_FILE
|
|
|
|
#define LIMITS_FILE "/etc/limits"
|
|
|
|
#endif
|
|
|
|
#define LOGIN_ERROR_RLIMIT 1
|
|
|
|
#define LOGIN_ERROR_LOGIN 2
|
|
|
|
/* Set a limit on a resource */
|
|
|
|
/*
|
|
|
|
* rlimit - RLIMIT_XXXX
|
|
|
|
* value - string value to be read
|
|
|
|
* multiplier - value*multiplier is the actual limit
|
|
|
|
*/
|
|
|
|
static int
|
2009-04-25 04:26:42 +05:30
|
|
|
setrlimit_value (unsigned int resource, const char *value,
|
2007-10-07 17:15:23 +05:30
|
|
|
unsigned int multiplier)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
struct rlimit rlim;
|
|
|
|
long limit;
|
|
|
|
|
2009-04-25 04:26:42 +05:30
|
|
|
if (getlong (value, &limit) == 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
limit *= multiplier;
|
2009-04-25 04:26:42 +05:30
|
|
|
if (limit != (rlim_t) limit) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
rlim.rlim_cur = (rlim_t) limit;
|
|
|
|
rlim.rlim_max = (rlim_t) limit;
|
|
|
|
if (setrlimit (resource, &rlim) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return LOGIN_ERROR_RLIMIT;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:15:23 +05:30
|
|
|
static int set_prio (const char *value)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2009-04-29 00:42:48 +05:30
|
|
|
long prio;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2009-04-29 00:42:48 +05:30
|
|
|
if ( (getlong (value, &prio) == 0)
|
|
|
|
|| (prio != (int) prio)) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2009-04-29 00:42:48 +05:30
|
|
|
if (setpriority (PRIO_PROCESS, 0, (int) prio) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return LOGIN_ERROR_RLIMIT;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:15:23 +05:30
|
|
|
static int set_umask (const char *value)
|
2007-10-07 17:14:08 +05:30
|
|
|
{
|
2009-04-25 04:26:42 +05:30
|
|
|
unsigned long int mask;
|
2007-10-07 17:14:08 +05:30
|
|
|
|
2009-04-25 04:26:42 +05:30
|
|
|
if ( (getulong (value, &mask) == 0)
|
|
|
|
|| (mask != (mode_t) mask)) {
|
2007-10-07 17:14:08 +05:30
|
|
|
return 0;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2009-04-25 04:26:42 +05:30
|
|
|
|
|
|
|
(void) umask ((mode_t) mask);
|
2007-10-07 17:14:08 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/* Counts the number of user logins and check against the limit */
|
2007-10-07 17:15:23 +05:30
|
|
|
static int check_logins (const char *name, const char *maxlogins)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2009-04-29 00:42:48 +05:30
|
|
|
#ifdef USE_UTMPX
|
2007-10-07 17:15:23 +05:30
|
|
|
struct utmpx *ut;
|
2009-04-29 00:42:48 +05:30
|
|
|
#else /* !USE_UTMPX */
|
2007-10-07 17:14:02 +05:30
|
|
|
struct utmp *ut;
|
2009-04-29 00:42:48 +05:30
|
|
|
#endif /* !USE_UTMPX */
|
2009-04-25 04:26:42 +05:30
|
|
|
unsigned long limit, count;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2009-04-25 04:26:42 +05:30
|
|
|
if (getulong (maxlogins, &limit) == 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-06-16 03:29:41 +05:30
|
|
|
if (0 == limit) { /* maximum 0 logins ? */
|
2007-10-07 17:15:23 +05:30
|
|
|
SYSLOG ((LOG_WARN, "No logins allowed for `%s'\n", name));
|
2007-10-07 17:14:02 +05:30
|
|
|
return LOGIN_ERROR_LOGIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
count = 0;
|
2009-04-29 00:42:48 +05:30
|
|
|
#ifdef USE_UTMPX
|
2007-10-07 17:15:23 +05:30
|
|
|
setutxent ();
|
|
|
|
while ((ut = getutxent ())) {
|
2009-04-29 00:42:48 +05:30
|
|
|
#else /* !USE_UTMPX */
|
2007-10-07 17:15:23 +05:30
|
|
|
setutent ();
|
|
|
|
while ((ut = getutent ())) {
|
2009-04-29 00:42:48 +05:30
|
|
|
#endif /* !USE_UTMPX */
|
2008-06-16 03:29:41 +05:30
|
|
|
if (USER_PROCESS != ut->ut_type) {
|
2007-10-07 17:14:02 +05:30
|
|
|
continue;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
|
|
|
if ('\0' == ut->ut_user[0]) {
|
2007-10-07 17:14:02 +05:30
|
|
|
continue;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
|
|
|
if (strncmp (name, ut->ut_user, sizeof (ut->ut_user)) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
continue;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
|
|
|
count++;
|
|
|
|
if (count > limit) {
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2009-04-29 00:42:48 +05:30
|
|
|
#ifdef USE_UTMPX
|
2007-10-07 17:15:23 +05:30
|
|
|
endutxent ();
|
2009-04-29 00:42:48 +05:30
|
|
|
#else /* !USE_UTMPX */
|
2007-10-07 17:15:23 +05:30
|
|
|
endutent ();
|
2009-04-29 00:42:48 +05:30
|
|
|
#endif /* !USE_UTMPX */
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* This is called after setutmp(), so the number of logins counted
|
|
|
|
* includes the user who is currently trying to log in.
|
|
|
|
*/
|
|
|
|
if (count > limit) {
|
2009-09-08 01:20:00 +05:30
|
|
|
SYSLOG ((LOG_WARN,
|
|
|
|
"Too many logins (max %lu) for %s\n",
|
|
|
|
limit, name));
|
2007-10-07 17:14:02 +05:30
|
|
|
return LOGIN_ERROR_LOGIN;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Function setup_user_limits - checks/set limits for the curent login
|
|
|
|
* Original idea from Joel Katz's lshell. Ported to shadow-login
|
|
|
|
* by Cristian Gafton - gafton@sorosis.ro
|
|
|
|
*
|
|
|
|
* We are passed a string of the form ('BASH' constants for ulimit)
|
2007-10-28 01:15:21 +05:30
|
|
|
* [Aa][Cc][Dd][Ff][Mm][Nn][Rr][Ss][Tt][Uu][Ll][Pp][Ii][Oo]
|
2007-10-07 17:14:02 +05:30
|
|
|
* (eg. 'C2F256D2048N5' or 'C2 F256 D2048 N5')
|
|
|
|
* where:
|
|
|
|
* [Aa]: a = RLIMIT_AS max address space (KB)
|
|
|
|
* [Cc]: c = RLIMIT_CORE max core file size (KB)
|
|
|
|
* [Dd]: d = RLIMIT_DATA max data size (KB)
|
2007-10-07 17:14:08 +05:30
|
|
|
* [Ff]: f = RLIMIT_FSIZE max file size (KB)
|
2007-10-07 17:14:02 +05:30
|
|
|
* [Mm]: m = RLIMIT_MEMLOCK max locked-in-memory address space (KB)
|
|
|
|
* [Nn]: n = RLIMIT_NOFILE max number of open files
|
|
|
|
* [Rr]: r = RLIMIT_RSS max resident set size (KB)
|
|
|
|
* [Ss]: s = RLIMIT_STACK max stack size (KB)
|
|
|
|
* [Tt]: t = RLIMIT_CPU max CPU time (MIN)
|
|
|
|
* [Uu]: u = RLIMIT_NPROC max number of processes
|
2007-10-07 17:14:08 +05:30
|
|
|
* [Kk]: k = file creation masK (umask)
|
2007-10-07 17:14:02 +05:30
|
|
|
* [Ll]: l = max number of logins for this user
|
2007-10-07 17:14:08 +05:30
|
|
|
* [Pp]: p = process priority -20..20 (negative = high, positive = low)
|
2007-10-28 01:15:21 +05:30
|
|
|
* [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19)
|
|
|
|
* [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO)
|
2007-10-07 17:14:02 +05:30
|
|
|
*
|
|
|
|
* Return value:
|
|
|
|
* 0 = okay, of course
|
|
|
|
* LOGIN_ERROR_RLIMIT = error setting some RLIMIT
|
|
|
|
* LOGIN_ERROR_LOGIN = error - too many logins for this user
|
|
|
|
*
|
|
|
|
* buf - the limits string
|
|
|
|
* name - the username
|
|
|
|
*/
|
2007-10-07 17:15:23 +05:30
|
|
|
static int do_user_limits (const char *buf, const char *name)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
const char *pp;
|
|
|
|
int retval = 0;
|
2008-06-16 03:29:41 +05:30
|
|
|
bool reported = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
pp = buf;
|
|
|
|
|
2008-06-16 03:29:41 +05:30
|
|
|
while ('\0' != *pp) {
|
2007-10-07 17:15:23 +05:30
|
|
|
switch (*pp++) {
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef RLIMIT_AS
|
|
|
|
case 'a':
|
|
|
|
case 'A':
|
|
|
|
/* RLIMIT_AS - max address space (KB) */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_AS, pp, 1024);
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
2007-10-07 17:14:02 +05:30
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_CPU
|
|
|
|
case 't':
|
|
|
|
case 'T':
|
|
|
|
/* RLIMIT_CPU - max CPU time (MIN) */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_CPU, pp, 60);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_DATA
|
|
|
|
case 'd':
|
|
|
|
case 'D':
|
|
|
|
/* RLIMIT_DATA - max data size (KB) */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_DATA, pp, 1024);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_FSIZE
|
|
|
|
case 'f':
|
|
|
|
case 'F':
|
|
|
|
/* RLIMIT_FSIZE - Maximum filesize (KB) */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_FSIZE, pp, 1024);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_NPROC
|
|
|
|
case 'u':
|
|
|
|
case 'U':
|
|
|
|
/* RLIMIT_NPROC - max number of processes */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_NPROC, pp, 1);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_CORE
|
|
|
|
case 'c':
|
|
|
|
case 'C':
|
|
|
|
/* RLIMIT_CORE - max core file size (KB) */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_CORE, pp, 1024);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_MEMLOCK
|
|
|
|
case 'm':
|
|
|
|
case 'M':
|
2007-10-07 17:15:23 +05:30
|
|
|
/* RLIMIT_MEMLOCK - max locked-in-memory address space (KB) */
|
2007-10-07 17:16:07 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_MEMLOCK, pp, 1024);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_NOFILE
|
|
|
|
case 'n':
|
|
|
|
case 'N':
|
|
|
|
/* RLIMIT_NOFILE - max number of open files */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_NOFILE, pp, 1);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_RSS
|
|
|
|
case 'r':
|
|
|
|
case 'R':
|
|
|
|
/* RLIMIT_RSS - max resident set size (KB) */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_RSS, pp, 1024);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_STACK
|
|
|
|
case 's':
|
|
|
|
case 'S':
|
|
|
|
/* RLIMIT_STACK - max stack size (KB) */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= setrlimit_value (RLIMIT_STACK, pp, 1024);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
2007-10-28 01:15:21 +05:30
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_NICE
|
|
|
|
case 'i':
|
|
|
|
case 'I':
|
|
|
|
/* RLIMIT_NICE - max scheduling priority (0..39) */
|
|
|
|
retval |= setrlimit_value (RLIMIT_NICE, pp, 1);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef RLIMIT_RTPRIO
|
|
|
|
case 'o':
|
|
|
|
case 'O':
|
|
|
|
/* RLIMIT_RTPRIO - max real time priority (0..MAX_RT_PRIO) */
|
|
|
|
retval |= setrlimit_value (RLIMIT_RTPRIO, pp, 1);
|
|
|
|
break;
|
2007-10-07 17:14:02 +05:30
|
|
|
#endif
|
2007-10-07 17:14:08 +05:30
|
|
|
case 'k':
|
|
|
|
case 'K':
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= set_umask (pp);
|
2007-10-07 17:14:08 +05:30
|
|
|
break;
|
2007-10-07 17:14:02 +05:30
|
|
|
case 'l':
|
|
|
|
case 'L':
|
2008-06-16 03:29:41 +05:30
|
|
|
/* LIMIT the number of concurrent logins */
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= check_logins (name, pp);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
case 'P':
|
2007-10-07 17:15:23 +05:30
|
|
|
retval |= set_prio (pp);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
2008-06-16 03:29:41 +05:30
|
|
|
default:
|
|
|
|
/* Only report invalid strings once */
|
|
|
|
if (!reported) {
|
|
|
|
SYSLOG ((LOG_WARN,
|
|
|
|
"Invalid limit string: '%s'",
|
|
|
|
pp-1));
|
|
|
|
reported = true;
|
|
|
|
retval |= LOGIN_ERROR_RLIMIT;
|
|
|
|
}
|
2007-10-07 17:15:23 +05:30
|
|
|
}
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2007-10-07 17:15:23 +05:30
|
|
|
static int setup_user_limits (const char *uname)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
/* TODO: allow and use @group syntax --cristiang */
|
|
|
|
FILE *fil;
|
|
|
|
char buf[1024];
|
|
|
|
char name[1024];
|
|
|
|
char limits[1024];
|
|
|
|
char deflimits[1024];
|
|
|
|
char tempbuf[1024];
|
|
|
|
|
|
|
|
/* init things */
|
2007-10-07 17:15:23 +05:30
|
|
|
memzero (buf, sizeof (buf));
|
|
|
|
memzero (name, sizeof (name));
|
|
|
|
memzero (limits, sizeof (limits));
|
|
|
|
memzero (deflimits, sizeof (deflimits));
|
|
|
|
memzero (tempbuf, sizeof (tempbuf));
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/* start the checks */
|
2007-10-07 17:15:23 +05:30
|
|
|
fil = fopen (LIMITS_FILE, "r");
|
2007-10-07 17:14:02 +05:30
|
|
|
if (fil == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* The limits file have the following format:
|
|
|
|
* - '#' (comment) chars only as first chars on a line;
|
|
|
|
* - username must start on first column
|
|
|
|
* A better (smarter) checking should be done --cristiang */
|
2007-10-07 17:15:23 +05:30
|
|
|
while (fgets (buf, 1024, fil) != NULL) {
|
2008-06-16 03:29:41 +05:30
|
|
|
if (('#' == buf[0]) || ('\n' == buf[0])) {
|
2007-10-07 17:14:02 +05:30
|
|
|
continue;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:15:23 +05:30
|
|
|
memzero (tempbuf, sizeof (tempbuf));
|
2007-10-07 17:14:02 +05:30
|
|
|
/* a valid line should have a username, then spaces,
|
|
|
|
* then limits
|
|
|
|
* we allow the format:
|
|
|
|
* username L2 D2048 R4096
|
|
|
|
* where spaces={' ',\t}. Also, we reject invalid limits.
|
|
|
|
* Imposing a limit should be done with care, so a wrong
|
|
|
|
* entry means no care anyway :-). A '-' as a limits
|
|
|
|
* strings means no limits --cristiang */
|
2007-10-28 01:15:21 +05:30
|
|
|
if (sscanf (buf, "%s%[ACDFMNRSTULPIOacdfmnrstulpio0-9 \t-]",
|
2007-10-07 17:15:23 +05:30
|
|
|
name, tempbuf) == 2) {
|
|
|
|
if (strcmp (name, uname) == 0) {
|
|
|
|
strcpy (limits, tempbuf);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
2007-10-07 17:15:23 +05:30
|
|
|
} else if (strcmp (name, "*") == 0) {
|
|
|
|
strcpy (deflimits, tempbuf);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-06-16 03:29:41 +05:30
|
|
|
(void) fclose (fil);
|
2007-10-07 17:14:02 +05:30
|
|
|
if (limits[0] == '\0') {
|
|
|
|
/* no user specific limits */
|
2008-06-16 03:29:41 +05:30
|
|
|
if (deflimits[0] == '\0') { /* no default limits */
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:15:23 +05:30
|
|
|
strcpy (limits, deflimits); /* use the default limits */
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:15:23 +05:30
|
|
|
return do_user_limits (limits, uname);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:15:23 +05:30
|
|
|
#endif /* LIMITS */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:08 +05:30
|
|
|
|
2007-10-07 17:15:23 +05:30
|
|
|
static void setup_usergroups (const struct passwd *info)
|
2007-10-07 17:14:08 +05:30
|
|
|
{
|
|
|
|
const struct group *grp;
|
2009-04-25 04:26:42 +05:30
|
|
|
mode_t tmpmask;
|
2007-10-07 17:14:08 +05:30
|
|
|
|
|
|
|
/*
|
2007-10-07 17:16:25 +05:30
|
|
|
* if not root, and UID == GID, and username is the same as primary
|
2007-10-07 17:14:08 +05:30
|
|
|
* group name, set umask group bits to be the same as owner bits
|
|
|
|
* (examples: 022 -> 002, 077 -> 007).
|
|
|
|
*/
|
2008-06-16 03:29:41 +05:30
|
|
|
if ((0 != info->pw_uid) && (info->pw_uid == info->pw_gid)) {
|
* lib/prototypes.h, configure.in, libmisc/Makefile.am,
libmisc/xgetXXbyYY.c, libmisc/xgetpwnam.c, libmisc/xgetpwuid.c,
libmisc/xgetgrnam.c, libmisc/xgetgrgid.c, libmisc/xgetspnam.c:
Added functions xgetpwnam(), xgetpwuid(), xgetgrnam(),
xgetgrgid(), and xgetspnam(). They allocate memory for the
returned structure and are more robust to successive calls. They
are implemented with the libc's getxxyyy_r() functions if
available.
* libmisc/limits.c, libmisc/entry.c, libmisc/chowntty.c,
libmisc/addgrps.c, libmisc/myname.c, libmisc/rlogin.c,
libmisc/pwdcheck.c, src/newgrp.c, src/login_nopam.c,
src/userdel.c, src/lastlog.c, src/grpck.c, src/gpasswd.c,
src/newusers.c, src/chpasswd.c, src/chfn.c, src/groupmems.c,
src/usermod.c, src/expiry.c, src/groupdel.c, src/chgpasswd.c,
src/su.c, src/useradd.c, src/groupmod.c, src/passwd.c, src/pwck.c,
src/groupadd.c, src/chage.c, src/login.c, src/suauth.c,
src/faillog.c, src/groups.c, src/chsh.c, src/id.c: Review all the
usage of one of the getpwnam(), getpwuid(), getgrnam(),
getgrgid(), and getspnam() functions. It was noticed on
http://bugs.debian.org/341230 that chfn and chsh use a passwd
structure after calling a pam function, which result in using
information from the passwd structure requested by pam, not the
original one. It is much easier to use the new xget... functions
to avoid these issues. I've checked which call to the original
get... functions could be left (reducing the scope of the
structure if possible), and I've left comments to ease future
reviews (e.g. /* local, no need for xgetpwnam */).
Note: the getpwent/getgrent calls should probably be checked also.
* src/groupdel.c, src/expiry.c: Fix typos in comments.
* src/groupmod.c: Re-indent.
* libmisc/Makefile.am, lib/groupmem.c, lib/groupio.c, lib/pwmem.c,
lib/pwio.c, lib/shadowmem.c, lib/shadowio.c: Move the __<xx>_dup
functions (used by the xget... functions) from the <xx>io.c files
to the new <xx>mem.c files. This avoid linking some utils against
the SELinux library.
2007-11-19 04:45:26 +05:30
|
|
|
/* local, no need for xgetgrgid */
|
2007-10-07 17:15:23 +05:30
|
|
|
grp = getgrgid (info->pw_gid);
|
2008-06-16 03:29:41 +05:30
|
|
|
if ( (NULL != grp)
|
|
|
|
&& (strcmp (info->pw_name, grp->gr_name) == 0)) {
|
2009-04-25 04:26:42 +05:30
|
|
|
tmpmask = umask (0777);
|
|
|
|
tmpmask = (tmpmask & ~070) | ((tmpmask >> 3) & 070);
|
|
|
|
(void) umask (tmpmask);
|
2007-10-07 17:14:08 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* set the process nice, ulimit, and umask from the password file entry
|
|
|
|
*/
|
|
|
|
|
2007-10-07 17:15:23 +05:30
|
|
|
void setup_limits (const struct passwd *info)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2007-10-07 17:15:23 +05:30
|
|
|
char *cp;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-06-16 03:29:41 +05:30
|
|
|
if (getdef_bool ("USERGROUPS_ENAB")) {
|
2007-10-07 17:15:23 +05:30
|
|
|
setup_usergroups (info);
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* See if the GECOS field contains values for NICE, UMASK or ULIMIT.
|
|
|
|
* If this feature is enabled in /etc/login.defs, we make those
|
|
|
|
* values the defaults for this login session.
|
|
|
|
*/
|
|
|
|
|
2007-10-07 17:15:23 +05:30
|
|
|
if (getdef_bool ("QUOTAS_ENAB")) {
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef LIMITS
|
2008-06-16 03:29:41 +05:30
|
|
|
if (info->pw_uid != 0) {
|
2007-10-07 17:15:23 +05:30
|
|
|
if (setup_user_limits (info->pw_name) &
|
|
|
|
LOGIN_ERROR_LOGIN) {
|
2008-06-16 03:29:41 +05:30
|
|
|
(void) fputs (_("Too many logins.\n"), stderr);
|
|
|
|
(void) sleep (2); /* XXX: Should be FAIL_DELAY */
|
* lib/exitcodes.h: Define E_SUCCESS as EXIT_SUCCESS. Added FIXMEs.
* libmisc/chowntty.c, libmisc/rlogin.c, libmisc/sub.c,
src/newusers.c, libmisc/sulog.c, libmisc/system.c, src/logoutd.c,
src/groups.c, src/id.c, lib/encrypt.c, libmisc/audit_help.c,
libmisc/limits.c: Return EXIT_FAILURE instead of 1, and
EXIT_SUCCESS instead of 0.
* libmisc/audit_help.c: Replace an fprintf() by fputs().
* libmisc/audit_help.c: Remove documentation of the audit_logger
returned values. The function returns void.
* libmisc/system.c: Only return status if waitpid succeeded.
Return -1 otherwise.
2009-05-01 02:38:49 +05:30
|
|
|
exit (EXIT_FAILURE);
|
2007-10-07 17:15:23 +05:30
|
|
|
}
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
#endif
|
2007-10-07 17:16:07 +05:30
|
|
|
for (cp = info->pw_gecos; cp != NULL; cp = strchr (cp, ',')) {
|
2008-06-16 03:29:41 +05:30
|
|
|
if (',' == *cp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
cp++;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
if (strncmp (cp, "pri=", 4) == 0) {
|
2009-04-25 04:26:42 +05:30
|
|
|
long int inc;
|
|
|
|
if ( (getlong (cp + 4, &inc) == 1)
|
|
|
|
&& (inc >= -20) && (inc <= 20)) {
|
2008-06-16 03:29:41 +05:30
|
|
|
errno = 0;
|
2009-04-25 04:26:42 +05:30
|
|
|
if ( (nice ((int) inc) != -1)
|
|
|
|
|| (0 != errno)) {
|
|
|
|
continue;
|
2008-06-16 03:29:41 +05:30
|
|
|
}
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2009-04-25 04:26:42 +05:30
|
|
|
/* Failed to parse or failed to nice() */
|
|
|
|
SYSLOG ((LOG_WARN,
|
|
|
|
"Can't set the nice value for user %s",
|
|
|
|
info->pw_name));
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (strncmp (cp, "ulimit=", 7) == 0) {
|
2009-04-25 04:26:42 +05:30
|
|
|
long int blocks;
|
|
|
|
if ( (getlong (cp + 7, &blocks) == 0)
|
|
|
|
|| (blocks != (int) blocks)
|
|
|
|
|| (set_filesize_limit ((int) blocks) != 0)) {
|
2008-06-16 03:29:41 +05:30
|
|
|
SYSLOG ((LOG_WARN,
|
|
|
|
"Can't set the ulimit for user %s",
|
|
|
|
info->pw_name));
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (strncmp (cp, "umask=", 6) == 0) {
|
2009-04-25 04:26:42 +05:30
|
|
|
unsigned long int mask;
|
|
|
|
if ( (getulong (cp + 6, &mask) == 0)
|
|
|
|
|| (mask != (mode_t) mask)) {
|
|
|
|
SYSLOG ((LOG_WARN,
|
|
|
|
"Can't set umask value for user %s",
|
|
|
|
info->pw_name));
|
|
|
|
} else {
|
|
|
|
(void) umask ((mode_t) mask);
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
|
2008-01-01 19:48:55 +05:30
|
|
|
#else /* !USE_PAM */
|
|
|
|
extern int errno; /* warning: ANSI C forbids an empty source file */
|
2007-10-07 17:16:07 +05:30
|
|
|
#endif /* !USE_PAM */
|
2008-04-27 06:10:09 +05:30
|
|
|
|