Monday, November 2, 2009

Hack 17 Control Login Access with PAM











 < Day Day Up > 





Hack 17 Control Login Access with PAM





Seize fine-grained control of when and where

your users can access your system
.





In traditional Unix

authentication there is not much granularity available in limiting a

user's ability to log in. For example, how would you

limit the hosts that users can come from when logging into your

servers? Your first thought might be to set up TCP wrappers or

possibly firewall rules [Hack #33]

and [Hack #34] . But what if you

wanted to allow some users to log in from a specific host, but

disallow others from logging in from it? Or what if you wanted to

prevent some users from logging in at certain times of the day

because of daily maintenance, but allow others (i.e., administrators)

to log in at any time they wish? To get this working with every

service that might be running on your system, you would traditionally

have to patch each of them to support this new functionality. This is

where PAM enters the picture.





PAM, or pluggable

authentication modules, allows for just this sort of functionality

(and more) without the need to patch all of your services. PAM has

been available for quite some time under Linux, FreeBSD, and Solaris,

and is now a standard component of the traditional authentication

facilities on these platforms. Many services that need to use some

sort of authentication now support PAM.





Modules are configured for services in a

stack, with the authentication process

proceeding from top to bottom as the access checks complete

successfully. You can build a custom stack for any service by

creating a file in /etc/pam.d with the same name

as the service. If you need even more granularity, an entire stack of

modules can be included by using the

pam_stack module. This allows you to specify

another external file containing a stack. If a service does not have

its own configuration file in /etc/pam.d, it

will default to using the stack specified in

/etc/pam.d/other.





When configuring a service for use with PAM, there are several types

of entries available. These types allow one to specify whether a

module provides authentication, access control, password change

control, or session setup and teardown. Right now, we are interested

in only one of the types: the account type. This entry type allows

you to specify modules that will control access to accounts that have

been authenticated. In addition to the service-specific configuration

files, some modules have extended configuration information that can

be specified in files within the /etc/security

directory. For this hack, we'll mainly use two of

the most useful modules of this type,

pam_access and pam_time.





The pam_access module allows one to limit where a

user or group of users may log in from. To make use of it,

you'll first need to configure the service you wish

to use the module with. You can do this by editing the

service's PAM config file in

/etc/pam.d.





Here's an example of what

/etc/pam.d/login might look like under Red Hat

9:





#%PAM-1.0

auth required pam_securetty.so

auth required pam_stack.so service=system-auth

auth required pam_nologin.so

account required pam_stack.so service=system-auth

password required pam_stack.so service=system-auth

session required pam_stack.so service=system-auth

session optional pam_console.so




Notice the use of the pam_stack module�it

includes the stack contained within the

system-auth file. Let's see

what's inside

/etc/pam.d/system-auth:





#%PAM-1.0

# This file is auto-generated.

# User changes will be destroyed the next time authconfig is run.

auth required /lib/security/$ISA/pam_env.so

auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok

auth required /lib/security/$ISA/pam_deny.so

account required /lib/security/$ISA/pam_unix.so

password required /lib/security/$ISA/pam_cracklib.so retry=3 type=

password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow

password required /lib/security/$ISA/pam_deny.so

session required /lib/security/$ISA/pam_limits.so

session required /lib/security/$ISA/pam_unix.so




To add the pam_access module to the login service,

you could add another account entry to the login configuration file,

which would, of course, just enable the module for the login service.

Alternatively, you could add the module to the

system-auth file, which would enable it for most

of the PAM-aware services on the system.





To add pam_access to the login service (or any

other service for that matter), simply add a line like this to the

service's configuration file after any preexisting

account entries:





account    required     pam_access.so




Now that we've enabled the

pam_access module for our services, we can edit

/etc/security/access.conf to control how the

module behaves. Each entry in the file can specify multiple users,

groups, and hostnames to which the entry applies, and specify whether

it's allowing or disallowing remote or local access.

When pam_access is invoked by an entry in a

service configuration file, it will look through the lines of

access.conf and stop at the first match it

finds. Thus, if you want to create default entries to fall back on,

you'll want to put the more specific entries first,

with the general entries following them.





The general form of an entry in access.conf is:





permission

:

users

:

origins




where permission can be either a

+ or -. This denotes whether

the rule grants or denies access, respectively.





The users portion allows you to specify a

list of users or groups, separated by whitespace. In addition to

simply listing users in this portion of the entry, you can use the

form

user@host,

where host is the local hostname of the

machine being logged into. This allows you to use a single

configuration file across multiple machines, but still specify rules

pertaining to specific machines. The

origins portion is compared against the

origin of the access attempt. Hostnames can be used for remote

origins, and the special LOCAL keyword can be used

for local access. Instead of explicitly specifying users, groups, or

origins, you can also use the ALL and

EXCEPT keywords to perform set operations on any

of the lists.





Here's a simple example of locking out the user

andrew (Eep! That's me!) from a host named

colossus:





- : andrew : colossus




Note that if a group that shares its name with a user is specified,

the module will interpret the rule as applying to both the user and

the group.





Now that we've covered

how to limit where a user may log in from and how to set up a PAM

module, let's take a look at how to limit what time

a user may log in by using the pam_time module. To

configure this module, you need to edit

/etc/security/time.conf. The format for the

entries in this file are a little more flexible than that of

access.conf, thanks to the availability of the

NOT (!), AND (&), and OR

(|) operators.





The general form for an entry in time.conf is:





services;devices;users;times




The services portion of the entry

specifies what PAM-enabled service will be regulated. You can usually

get a full list of the available services by looking at the contents

of your /etc/pam.d directory.





For instance, here's the

contents of

/etc/pam.d on a RedHat Linux system:





$ ls -1 /etc/pam.d

authconfig

chfn

chsh

halt

internet-druid

kbdrate

login

neat

other

passwd

poweroff

ppp

reboot

redhat-config-mouse

redhat-config-network

redhat-config-network-cmd

redhat-config-network-druid

rhn_register

setup

smtp

sshd

su

sudo

system-auth

up2date

up2date-config

up2date-nox

vlock




To set up pam_time for use with any of these

services, you'll need to add a line like this to the

file in /etc/pam.d that corresponds to the

service that you want to regulate:





account     required      /lib/security/$ISA/pam_time.so




The devices portion specifies the terminal

device that the service is being accessed from. For console logins,

you can use !ttyp*, which specifies all TTY

devices except for pseudo TTYs. If you want the entry to only affect

remote logins, then use ttyp*. You can restrict it

to all users (console, remote, and X11) by using

tty*.





For the users portion of the entry, you can

specify a single user or a list of users by separating each one with

a | character. The times

portion is used to specify the times that the rule will apply. Each

time range is specified with a combination of two character

abbreviations, which denote the days that the rule will apply,

followed with a range of hours for that day. The abbreviations for

the days of the week are Mo,

Tu, We, Th,

Fr, Sa, and

Su. For convenience you can use

Wk to specify weekdays and Wd

to specify the weekend. In addition, you can use

Al to specify every day of the week. These last

three basically expand to the set of days that compose each time

period. This is important to remember, since repeated days are

subtracted from the set of days that the rule will apply to (e.g.,

WkSu would effectively be just

Sa). The range of hours is simply specified as two

24-hour times, minus the colons, separated by a dash (e.g., 0630-1345

is 6:30 A.M. to 1:45 P.M.).





If you wanted to disallow access to the user andrew from the local

console on weekends and during the week after hours, you could use an

entry like this:





system-auth;!ttyp*;andrew;Wk1700-0800|Wd0000-2400




Or perhaps you want to limit remote logins through SSH during a

system maintenance window lasting from 7 P.M. Friday to 7 A.M.

Saturday, but want to allow a sysadmin to log in:





sshd;ttyp*;!andrew;Fr1900-0700




As you can see, there's a lot of flexibility for

creating entries, thanks to the logical Boolean operators that are

available. Just make sure that you remember to configure the service

file in /etc/pam.d for use with

pam_time when you create entries in

/etc/security/time.conf.

















     < Day Day Up > 



    No comments:

    Post a Comment