[Samba-it] pam & cambio password(posix/win) linux-side

Marco Gaiarin gaio at sv.lnf.it
Thu Jan 28 11:30:09 MST 2010


Mandi! Simone
  In chel di` si favelave...

> Qualcuno ha già trovato una soluzione al problema? Se sì, come ha
> configurato i pam ?

Per forza, necessità di cose, occorre usare winbind e pam_winbind.

Non serve installare samba sulla macchina, basta installare winbind
e mettere la macchina in join a dominio.

La configurazione sicuramente più 'pulita' è quella di usare winbind
per tutti i contesti pam in cui ha senso e per nss; se come me sei
pazzo e paranoico (nei confronti di winbind) io sono riuscito ad
usarlo solo nel contesto password (per il cambio password).

Allego il mio profilo di auth-client-config in ubuntu e lo script che
uso per 'sincronizzare' le scadenza delle password tra samba e POSIX.


...è un po' che non ci gioco, se qualcuno ha qualche modifica che dica
pure...

-- 
dott. Marco Gaiarin				    GNUPG Key ID: 240A3D66
  Associazione ``La Nostra Famiglia''                http://www.sv.lnf.it/
  Polo FVG  -  Via della Bontà, 7 - 33078  -  San Vito al Tagliamento (PN)
  marco.gaiarin(at)sv.lnf.it	  tel +39-0434-842711  fax +39-0434-842797

		Dona il 5 PER MILLE a LA NOSTRA FAMIGLIA!
	   http://www.lanostrafamiglia.it/chi_siamo/5xmille.php
	(cf 00307430132, categoria ONLUS oppure RICERCA SANITARIA)
-------------- next part --------------

1) occorre che la macchina sia in join a dominio, ma non serve che ci sia
 samba in esecuzione, basta samba-common e winbind.
Occorre configurare smb.conf al minimo, stile:

 [global]
	workgroup = SANVITO
	server string = %h server (Samba, Ubuntu)
	security = DOMAIN
	guest account = guest
	syslog = 0
	log file = /var/log/samba/log.%m
	max log size = 1000
	dns proxy = No
	wins server = 10.5.1.3
	panic action = /usr/share/samba/panic-action %d
	idmap domains = SANVITO
	winbind use default domain = Yes
	idmap config SANVITO:backend = nss
	idmap config SANVITO:readonly = yes
	idmap config SANVITO:default = yes


2) il mapping avviene attraverso il nome di utenti e gruppi e quindi
 QUESTO DEVE COINCIDERE, ovvero nomi POSIX e Win di utenti e gruppi
devono essere gli stessi.
Per i gruppi potrebbe bastare anche un mapping locale, ma è un hack
e potrebbe smettere di funzonare di punto in bianco.


More info su:

	http://lists.xsec.it/pipermail/samba-it/2008-December/007813.html

ed eventualmente tutto il thread precedente. ;)
-------------- next part --------------
#
# Configurazione mista che utilizza LDAP per i contesti password ed account
# mentre utilizza winbind per il contesto password, per permettere il
# cambiamento della pass con gli strumenti di windows.
#
# Alcune note:
#  + NSS non supporta shadow,
#     /usr/share/doc/libnss-ldap/LDAP-Permissions.txt.gz
#    ma posso ovviare con il contesto specifico 'account'
#  + onde evitare errori inutili, uso pam_localuser per identificare gli
#    utenti locali.
#  + la configurazione di winbind necessita solo del join e della corretta
#    configurazione dell'idmap nss.
# 
[ldap-wb]
nss_passwd=passwd: files ldap
nss_group=group: files ldap
nss_shadow=shadow: files 
pam_auth=auth	[success=ignore default=1]		pam_localuser.so
	auth	[success=1 default=ignore]		pam_unix.so nullok_secure
	auth	required				pam_ldap.so try_first_pass
	auth	required				pam_permit.so
pam_account=account	[success=ignore default=1]	pam_localuser.so
	account [success=1 default=ignore]		pam_unix.so
	account	required				pam_ldap.so
	account	required				pam_permit.so
pam_session=session required				pam_unix.so
pam_password=password	[success=ignore default=1]	pam_localuser.so
	password [success=1 default=ignore]		pam_unix.so nullok obscure min=4 max=8 md5
	password required				pam_winbind.so try_first_pass
	password required				pam_permit.so
-------------- next part --------------
#!/usr/bin/perl -w

#  This code was developped by Marco Gaiarin <gaio at linux.it>
#  taking ideas and code from smbldap-tools script by IDEALX
#  (http://IDEALX.org/) and
#
#                 Copyright (C) 2006 Marco Gaiarin
#                 Copyright (C) 2001-2002 IDEALX
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
#  USA.

# Purpose of smbldap-userexpire: expire user (posix,shadow,samba) after some
#				 inactivity time

# CHANGELOG
#
# (Thu Jul 20 16:12:39 CEST 2006)
#  + added -P options, rename all POSIX options
#  + considering the case sambaLogonTime < sambaPwdLastSet


use strict;
use smbldap_tools;

#####################

use Getopt::Std;
my %Options;

# getting some info from config file
#
my $pwdage = 90;
if (defined $config{defaultMaxPasswordAge}) {
  $pwdage = $config{defaultMaxPasswordAge};
}
my $acctage = 180;
my $pxpwdage = 210;
my $pxacctage = 360;
my $pxwarndays = 7;
 

my $ok = getopts('vdfsp:a:P:A:W:h?', \%Options);
if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) || ($Options{'h'}) ) {
  print_banner;
  print "Usage: $0 [-vdfs?h] [-p days] [-a days] [-P days] [-A days] [-W days] username\n";
  print "Available options are:\n";
  print "  -v    verbose mode\n";
  print "  -d    dry-run (do all the checks but just not update)\n";
  print "  -f    fix broken/impossible value\n";
  print "  -s    fix also POSIX/shadow account information\n";
  print "  -p    password age, default $pwdage (in days)\n";
  print "  -a    account age, default $acctage (in days)\n";
  print "  -P    POSIX password age, default $pxpwdage (in days)\n";
  print "  -A    POSIX account age, default $pxacctage (in days)\n";
  print "  -W    POSIX warning days before expiring, default $pxwarndays (in days)\n";
  print "  -?|-h show this help message\n";
  exit (1);
}

if ($< != 0) {
  print "You must be root to modify an user\n";
  exit (1);
}
# Read only first @ARGV
my $user = $ARGV[0];

# Let's connect to the directory first
my $ldap_master=connect_ldap_master();

# Read user data
my $user_entry = read_user_entry($user);
if (!defined($user_entry)) {
  if ($Options{'v'}) {
    print "$0: user $user doesn't exist\n";
  }
  exit (1);
}
my $dn = $user_entry->dn();

# no samba? no party!
if ( ! grep ($_ =~ /^sambaSamAccount$/i, $user_entry->get_value('objectClass'))) {
  if ($Options{'v'}) {
    print "$0: user $user doesn't have samba data, nothing to do.\n";
  }
  exit(1);
}

# some vars...
my @mods;
my $tmp;
my constant $max = 2147483647;
my $retval = 0;
my $curdate = time;

# reapup account ages on commandline...
if (defined($tmp = $Options{'p'})) {
  $pwdage = int($tmp);
}
if (defined($tmp = $Options{'a'})) {
  $acctage = int($tmp);
}
if (defined($tmp = $Options{'P'})) {
  $pxpwdage = int($tmp);
}
if (defined($tmp = $Options{'A'})) {
  $pxacctage = int($tmp);
}
if (defined($tmp = $Options{'W'})) {
  $pxwarndays = int($tmp);
}

# Eventually adding missing shadowAccount OC
if ( ($Options{'s'}) && (! grep ($_ =~ /^shadowAccount$/i, $user_entry->get_value('objectClass'))) ) {
  my @objectclass = $user_entry->get_value('objectClass');
  push(@mods, 'objectClass' => [ @objectclass, 'shadowAccount' ]);
  if ($Options{'v'}) {
    print "$0: user $user shadowAccount ObjectClass missing added\n";
  }
}

# Password expiration are handled automatically by samba, here we do only
# some check... note that we use a theresold value of one day for password
# expiration...
my $pls = $user_entry->get_value('sambaPwdLastSet');
my $pmc = $user_entry->get_value('sambaPwdMustChange');
if (! defined($pmc) ) {
  $pmc = 0;
}
my $af = $user_entry->get_value('sambaAcctFlags');
if ($Options{'f'}) {
  if ( $pls > $curdate ) {
    $pls = $curdate;  
    if ($Options{'v'}) {
      print "$0: user $user sambaPwdLastSet invalid, resetting to $pls\n";
    }
    push(@mods, 'sambaPwdLastSet' => $pls);
  }

  if ( $pmc > $curdate + (($pwdage+1)*24*60*60) ) {
    $pmc = $curdate;
    if ($Options{'v'}) {
      print "$0: user $user sambaPwdMustChange too high, resetting to $pmc\n";
    }
    push(@mods, 'sambaPwdMustChange' => $pmc);
  }

  if ( $af =~ /X/ ) {
    if ($Options{'v'}) {
      print "$0: user $user sambaAcctFlags 'X' enabled, resetting it\n";
    }
    $af =~ s/X//;
    push(@mods, 'sambaAcctFlags' => $af);
  }
}


# account expiration/disabling...
my $lot = $user_entry->get_value('sambaLogonTime');
if (! defined($lot) ) {
  $lot = 0;
}
if ( $lot < $pls ) {
  # strange, this user have a logon time smaller than last pwd set, could
  # be a real UNIX guy that use smbpasswd by hand?
  # anyway we consider this an access...
  if ($Options{'v'}) {
    print "$0: user $user sambaPwdLastSet considered as an access\n";
  }
  $lot = $pls;
  push(@mods, 'sambaLogonTime' => $lot);
}
if ( ($lot < $curdate - ($acctage*24*60*60)) && ($af !~ /D/) ) {
  if ($Options{'v'}) {
    print "$0: user $user sambaLogonTime too low, disabling account\n";
  }
  $af =~ s/U/DU/;
  push(@mods, 'sambaAcctFlags' => $af);
  $retval = 2;

  # if we are using shadow, this could be excessive, but better do this
  # then risk to have and open access lying around...
  my $up = $user_entry->get_value('userPassword');
  if ( ($Options{'s'}) && ($lot < $curdate - ($pxacctage*24*60*60)) && ($up !~ /^{crypt}x$/) ) {
    if ($Options{'v'}) {
      print "$0: user $user sambaLogonTime really too low, disabling POSIX account\n";
    }
    $up = "{crypt}x";
    push(@mods, 'userPassword' => $up);
  }
}

# poking POSIX shadow data...
if ( $Options{'s'} ) {
  my $lc = $user_entry->get_value('shadowLastChange');
  if ( ! defined($lc) ) {
    $lc = 0;
  }
  my $slc = int ($pls/(24*60*60));
  if ( $lc != $slc ) {
    if ($Options{'v'}) {
      print "$0: user $user setting up shadow data\n";
    }
    push(@mods, 'shadowLastChange' => $slc);
    push(@mods, 'shadowMin' => 0);
    push(@mods, 'shadowMax' => $pxpwdage);
    push(@mods, 'shadowWarning' => $pxwarndays);
    push(@mods, 'shadowInactive' => ($pxacctage - $pxpwdage) );
  }
}

# apply changes
if ( (@mods) && (! $Options{'d'}) ) {
  my $modify = $ldap_master->modify ( "$dn",
				    'replace' => { @mods }
				  );
  $modify->code && warn "failed to modify entry: ", $modify->error ;
}

# take down session
$ldap_master->unbind;

# need to tackle with nscd...
if ( (@mods) && (! $Options{'d'}) ) {
  my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
  if ($nscd_status == 0) {
    system "/etc/init.d/nscd restart > /dev/null 2>&1";
  }
} 

# we exit with a well-known exit status, so if we change something
# important we can warn users...
exit($retval);

############################################################

=head1 NAME

smbldap-userexpire - Expire user account based on last access time

=head1 SYNOPSIS

smbldap-userexpire [-v] [-d] [-f] [-s] [-p days] [-a days] [-x days] login

=head1 DESCRIPTION

The  smbldap-userexpire  command  check for account access timestamp, and update account info accordingly, typically disabling account if not used by some time.

-v
 Verbose mode, print any action taken

-d
 Dry-run, actually compute all needed modification but not apply them; usually used in conjunction with -v

-f
 Fix broken/impossible data, that can prevent an account to expire

-s
 Fix also POSIX/shadow data; note that LDAP shadow data can not be used, so this script also set the POSIX password invalid

-p days
 Password age in days (also use defaultMaxPasswordAge in smbldap.conf)

-a days
 Samba Account age in days

-P days
 POSIX password age in days

-A days
 POSIX Account age in days

-W days
 POSIX warning days before expiring; in PAM-enabled environment, the POSIX layer will warn users that password are expiring


=head1 RETURN VALUES

This script return 0 if all goes well, 1 if something goes wrong and 2 if all goes well and a Samba account was disabled.

This is intended so you can catch return value, and do something (send an email, ...) to user. For the same reason Samba account age <> POSIX account age, with the latter better to be highest then the former.

=head1 SEE ALSO

       smbldap-usermod(1) smbldap-useraccess(1) chage(1)

=cut

#'


More information about the samba-it mailing list