- Added the functionality to handle change password in PAM system
This commit is contained in:
parent
06000507be
commit
f4bf118742
@ -2,6 +2,7 @@ VER_1.0
|
||||
{
|
||||
global:
|
||||
pam_sm_authenticate;
|
||||
pam_sm_chauthtok;
|
||||
pam_sm_setcred;
|
||||
pam_sm_acct_mgmt;
|
||||
pam_sm_open_session;
|
||||
|
@ -2,6 +2,7 @@ VER_1.0
|
||||
{
|
||||
global:
|
||||
pam_sm_authenticate;
|
||||
pam_sm_chauthtok;
|
||||
pam_sm_setcred;
|
||||
pam_sm_acct_mgmt;
|
||||
pam_sm_open_session;
|
||||
|
@ -29,147 +29,257 @@
|
||||
*
|
||||
* This module needs to be present before any other PAM module which
|
||||
* requires the services of miCASAd. It needs to be present
|
||||
* the auth stacks of the PAM configuration files.
|
||||
* the auth and password stacks of the PAM configuration files.
|
||||
*
|
||||
* In the auth stack, the functionality of the module is to store
|
||||
* the workstation user/password in micasad.
|
||||
*
|
||||
* In the password stack, the functionality of the module is to capture
|
||||
* the new password during change password operation and updating
|
||||
* the same in micasad.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "pam_sscs.h"
|
||||
|
||||
#define PAM_SM_AUTH
|
||||
#define PAM_SM_PASSWORD
|
||||
#define PAM_SM_ACCOUNT
|
||||
#define PAM_SM_SESSION
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,
|
||||
const char **argv)
|
||||
/*
|
||||
* Running (micasad_status = 1)
|
||||
* Not Running (micasad_status = 0)
|
||||
*/
|
||||
static int micasad_status = 0;
|
||||
|
||||
int is_micasad_running(void)
|
||||
{
|
||||
int retVal = 0;
|
||||
FILE *pid_file = NULL;
|
||||
char pid_str[MICASAD_PID_SIZE];
|
||||
pid_t pid;
|
||||
|
||||
const char *user = NULL;
|
||||
const char *wkstnPasswd = NULL;
|
||||
pid_file = fopen (MICASAD_PID_FILE, "r");
|
||||
if (!pid_file)
|
||||
return 0;
|
||||
|
||||
uid_t saved_uid = geteuid();
|
||||
struct passwd *passwdEntry = NULL;
|
||||
if (!fgets (pid_str, MICASAD_PID_SIZE, pid_file)) {
|
||||
fclose (pid_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the username first.
|
||||
*/
|
||||
retVal = pam_get_user(pamh, &user, NULL);
|
||||
fclose (pid_file);
|
||||
|
||||
if ( PAM_SUCCESS != retVal )
|
||||
{
|
||||
pam_sscs_log( LOG_ERR, "pam_get_user returned error: %d - %s\n",retVal,pam_strerror(pamh,retVal));
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
pid = atoi (pid_str);
|
||||
if ( pid < 2 )
|
||||
return 0;
|
||||
|
||||
pam_get_item(pamh,PAM_AUTHTOK,(const void**)&wkstnPasswd);
|
||||
passwdEntry = getpwnam(user);
|
||||
return (!kill(pid, 0));
|
||||
}
|
||||
|
||||
void set_micasa_password(const char *user, const char *password)
|
||||
{
|
||||
uid_t saved_uid = geteuid();
|
||||
struct passwd *passwdEntry = NULL;
|
||||
int retval = 0;
|
||||
|
||||
/* Set the desktop password in miCASA */
|
||||
passwdEntry = getpwnam(user);
|
||||
if( passwdEntry ) {
|
||||
/* CASA determines the client uid using the SO_PEERCRED socket option.
|
||||
* Hence the euid is temporarily modified to that of the user logging in.
|
||||
*/
|
||||
if(passwdEntry)
|
||||
{
|
||||
seteuid( passwdEntry->pw_uid );
|
||||
seteuid(passwdEntry -> pw_uid);
|
||||
do {
|
||||
char *error = NULL;
|
||||
SSCS_SECRET_ID_T secretID = {0};
|
||||
SSCS_BASIC_CREDENTIAL basicCredential;
|
||||
|
||||
do
|
||||
{
|
||||
char *error = NULL;
|
||||
SSCS_SECRET_ID_T secretID = {0};
|
||||
SSCS_BASIC_CREDENTIAL basicCredential;
|
||||
int credType;
|
||||
void *nsscsIdkHandle = dlopen(NSSCSIDK_LIB, RTLD_NOW);
|
||||
if( NULL == nsscsIdkHandle ) {
|
||||
pam_sscs_log(LOG_ERR,"Unable to open %s\n", NSSCSIDK_LIB);
|
||||
break;
|
||||
}
|
||||
|
||||
void *nsscsIdkHandle = dlopen(NSSCSIDK_LIB,RTLD_NOW);
|
||||
if( NULL == nsscsIdkHandle )
|
||||
{
|
||||
pam_sscs_log(LOG_ERR,"Unable to open %s\n",NSSCSIDK_LIB);
|
||||
break;
|
||||
}
|
||||
pNSSCSSetCredential = dlsym(nsscsIdkHandle, "miCASASetCredential");
|
||||
if( (error = dlerror()) != NULL ) {
|
||||
pam_sscs_log(LOG_ERR,"Unable to find miCASASetCredential symbol.- %s\n",error);
|
||||
break;
|
||||
}
|
||||
|
||||
pNSSCSSetCredential = dlsym( nsscsIdkHandle,
|
||||
"miCASASetCredential");
|
||||
if( (error = dlerror()) != NULL )
|
||||
{
|
||||
pam_sscs_log(LOG_ERR,"Unable to find miCASASetCredential symbol.- %s\n",error);
|
||||
break;
|
||||
}
|
||||
secretID.len = strlen(WORKSTATION_SECRET_ID) + 1;
|
||||
strcpy(secretID.id,WORKSTATION_SECRET_ID);
|
||||
|
||||
secretID.len = strlen(WORKSTATION_SECRET_ID) + 1;
|
||||
strcpy(secretID.id,WORKSTATION_SECRET_ID);
|
||||
memset(&basicCredential,0,sizeof(basicCredential));
|
||||
|
||||
memset(&basicCredential,0,sizeof(basicCredential));
|
||||
if (user && password) {
|
||||
basicCredential.unFlags = 0;
|
||||
// don't copy a username longer than we can handle
|
||||
if ((strlen(user) + 1) > NSSCS_MAX_USERID_LEN) {
|
||||
pam_sscs_log( LOG_ERR,"Username is longer than allowed\n");
|
||||
break;
|
||||
}
|
||||
strcpy(basicCredential.username,user);
|
||||
basicCredential.unLen = strlen(user) + 1;
|
||||
|
||||
if (user && wkstnPasswd)
|
||||
{
|
||||
basicCredential.unFlags = 0;
|
||||
// don't copy a username longer than we can handle
|
||||
if ((strlen(user) + 1) > NSSCS_MAX_USERID_LEN)
|
||||
{
|
||||
pam_sscs_log( LOG_ERR,"Username is longer than allowed\n");
|
||||
break;
|
||||
}
|
||||
strcpy(basicCredential.username,user);
|
||||
basicCredential.unLen = strlen(user) + 1;
|
||||
// don't copy a password longer than we can handle
|
||||
if ((strlen(password) + 1) > NSSCS_MAX_PWORD_LEN) {
|
||||
pam_sscs_log( LOG_ERR,"Password is longer than allowed\n");
|
||||
break;
|
||||
}
|
||||
strcpy(basicCredential.password,password);
|
||||
basicCredential.pwordLen = strlen(password) + 1;
|
||||
|
||||
// don't copy a password longer than we can handle
|
||||
if ((strlen(wkstnPasswd) + 1) > NSSCS_MAX_PWORD_LEN)
|
||||
{
|
||||
pam_sscs_log( LOG_ERR,"Password is longer than allowed\n");
|
||||
break;
|
||||
}
|
||||
strcpy(basicCredential.password,wkstnPasswd);
|
||||
basicCredential.pwordLen = strlen(wkstnPasswd) + 1;
|
||||
retval = (*pNSSCSSetCredential) (0,
|
||||
&secretID,
|
||||
NULL,
|
||||
SSCS_CRED_TYPE_BASIC_F,
|
||||
&basicCredential,
|
||||
NULL);
|
||||
if( retval != 0) {
|
||||
pam_sscs_log( LOG_ERR,"Setting the default credential failed.Errcode = %d\n",retval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
seteuid(saved_uid);
|
||||
}
|
||||
|
||||
retVal = (*pNSSCSSetCredential) (0,
|
||||
&secretID,
|
||||
NULL,
|
||||
SSCS_CRED_TYPE_BASIC_F,
|
||||
&basicCredential,
|
||||
NULL);
|
||||
if( retVal != 0)
|
||||
{
|
||||
pam_sscs_log( LOG_ERR,"Setting the default credential failed.Errcode = %d\n",retVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}while(0);
|
||||
return;
|
||||
}
|
||||
|
||||
seteuid(saved_uid);
|
||||
/* --- authentication management function --- */
|
||||
|
||||
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,const char **argv)
|
||||
{
|
||||
int retval = 0;
|
||||
const char *user = NULL, *wkstnPasswd = NULL;
|
||||
|
||||
if ( !is_micasad_running() ) {
|
||||
pam_sscs_log(LOG_DEBUG, "micasad is not running.\n");
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get the username */
|
||||
retval = pam_get_user(pamh, &user, NULL);
|
||||
if ( PAM_SUCCESS != retval ) {
|
||||
pam_sscs_log( LOG_ERR,
|
||||
"pam_get_user returned error: %d - %s\n",
|
||||
retval,
|
||||
pam_strerror(pamh,retval));
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Get the password */
|
||||
retval = pam_get_item(pamh, PAM_AUTHTOK, (const void**)&wkstnPasswd);
|
||||
if ( PAM_SUCCESS != retval ) {
|
||||
pam_sscs_log(LOG_ERR,
|
||||
"pam_get_item returned: %d - %s\n",
|
||||
retval,
|
||||
pam_strerror(pamh, retval));
|
||||
return (retval);
|
||||
}
|
||||
else if ( !wkstnPasswd ) {
|
||||
pam_sscs_log(LOG_AUTHPRIV,
|
||||
"pam_get_item returned a NULL pointer for the password\n");
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Set the password in micasad*/
|
||||
set_micasa_password(user, wkstnPasswd);
|
||||
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc,const char **argv)
|
||||
{
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
/* --- account management functions --- */
|
||||
/* --- password management function --- */
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
{
|
||||
int retval = 0;
|
||||
const char *user = NULL, *new_passwd = NULL;
|
||||
|
||||
/* Get the username */
|
||||
retval = pam_get_user(pamh, &user, NULL);
|
||||
if ( PAM_SUCCESS != retval ) {
|
||||
pam_sscs_log(LOG_ERR,
|
||||
"pam_get_user returned: %d - %s\n",
|
||||
retval,
|
||||
pam_strerror(pamh,retval));
|
||||
return (retval);
|
||||
}
|
||||
|
||||
if ( flags & PAM_PRELIM_CHECK ) {
|
||||
|
||||
if ( is_micasad_running() )
|
||||
micasad_status = 1;
|
||||
else
|
||||
micasad_status = 0;
|
||||
|
||||
return (PAM_SUCCESS);
|
||||
} /* End of PAM_PRELIM_CHECK */
|
||||
else if ( flags & PAM_UPDATE_AUTHTOK ) {
|
||||
|
||||
if( !micasad_status ) {
|
||||
pam_sscs_log(LOG_DEBUG, "micasad is not running.\n");
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get the new password */
|
||||
retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&new_passwd);
|
||||
if( PAM_SUCCESS != retval ) {
|
||||
pam_sscs_log(LOG_ERR,
|
||||
"pam_get_item returned: %d - %s\n",
|
||||
retval,
|
||||
pam_strerror(pamh, retval));
|
||||
return (retval);
|
||||
}
|
||||
else if ( !new_passwd ) {
|
||||
pam_sscs_log(LOG_AUTHPRIV, "pam_get_item returned a NULL pointer for the new password\n");
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Set the new password in micasad*/
|
||||
set_micasa_password(user, new_passwd);
|
||||
|
||||
} /*End of PAM_UPDATE_AUTHTOK */
|
||||
else {
|
||||
pam_sscs_log(LOG_DEBUG, "Neither PAM_PRELIM_CHECK nor PAM_UPDATE_AUTHTOK flag is set.\n");
|
||||
return (PAM_AUTH_ERR);
|
||||
} /* End of some other flag (Other than PAM_PRELIM_CHECK or PAM_UPDATE_AUTHTOK */
|
||||
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
/* --- account management function --- */
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc,const char **argv)
|
||||
{
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
/* --- session management functions --- */
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc,const char **argv)
|
||||
{
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
PAM_EXTERN
|
||||
int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc,const char **argv)
|
||||
{
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
@ -177,22 +287,15 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
|
||||
/* end of module definition */
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* static module data */
|
||||
|
||||
struct pam_module _pam_passphrase_modstruct = {
|
||||
"pam_sscs",
|
||||
"pam_micasa",
|
||||
pam_sm_authenticate,
|
||||
pam_sm_setcred,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
pam_sm_acct_mgmt,
|
||||
pam_sm_open_session,
|
||||
pam_sm_close_session,
|
||||
#if 0
|
||||
pam_sm_chauthtok
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,57 +20,60 @@
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
/*
|
||||
pam_sscs.h
|
||||
*/
|
||||
#ifndef _PAM_SSCS_H
|
||||
#define _PAM_SSCS_H
|
||||
#include <dlfcn.h>
|
||||
#include <security/_pam_types.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <linux/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <micasa.h>
|
||||
|
||||
extern void pam_sscs_log(int priority, const char *format,...);
|
||||
|
||||
#define WORKSTATION_SECRET_ID "Desktop"
|
||||
#define WORKSTATION_SHARED_SECRET_ID "DefaultSharedSecret"
|
||||
|
||||
#define NSSCSIDK_LIB "libmicasa.so"
|
||||
|
||||
#define NOVELL_CSSS_CONTEXT "NOVELL_CSSS_CONTEXT"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define PRINT_FN_NAME pam_sscs_log(LOG_DEBUG,"In function : %s\n",__func__);
|
||||
#else
|
||||
#define PRINT_FN_NAME
|
||||
#endif
|
||||
|
||||
void* (*pNSSCSOpenSecretStoreCache) ( SSCS_SECRETSTORE_T* ssid,
|
||||
unsigned long ssFlags,
|
||||
SSCS_EXT_T *ext);
|
||||
int (*pNSSCSCloseSecretStoreCache) ( void *context,
|
||||
unsigned long ssFlags,
|
||||
SSCS_EXT_T *ext);
|
||||
int (*pNSSCSSetCredential) ( unsigned long ssFlags,
|
||||
SSCS_SECRET_ID_T *appSecretID,
|
||||
SSCS_SECRET_ID_T *sharedSecretID,
|
||||
int credentialType,
|
||||
void *credential,
|
||||
SSCS_EXT_T *ext);
|
||||
|
||||
/* The structure to hold all the possible options
|
||||
* for this PAM module.
|
||||
*/
|
||||
typedef struct options_t
|
||||
{
|
||||
unsigned int debug;
|
||||
}Options;
|
||||
|
||||
#endif
|
||||
/*
|
||||
pam_sscs.h
|
||||
*/
|
||||
#ifndef _PAM_SSCS_H
|
||||
#define _PAM_SSCS_H
|
||||
#include <dlfcn.h>
|
||||
#include <security/_pam_types.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <linux/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <micasa.h>
|
||||
|
||||
extern void pam_sscs_log(int priority, const char *format,...);
|
||||
|
||||
#define WORKSTATION_SECRET_ID "Desktop"
|
||||
#define WORKSTATION_SHARED_SECRET_ID "DefaultSharedSecret"
|
||||
|
||||
#define NSSCSIDK_LIB "libmicasa.so"
|
||||
|
||||
#define NOVELL_CSSS_CONTEXT "NOVELL_CSSS_CONTEXT"
|
||||
|
||||
#define MICASAD_PID_SIZE 32
|
||||
#define MICASAD_PID_FILE "/var/run/micasad.pid"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define PRINT_FN_NAME pam_sscs_log(LOG_DEBUG,"In function : %s\n",__func__);
|
||||
#else
|
||||
#define PRINT_FN_NAME
|
||||
#endif
|
||||
|
||||
void* (*pNSSCSOpenSecretStoreCache) ( SSCS_SECRETSTORE_T* ssid,
|
||||
unsigned long ssFlags,
|
||||
SSCS_EXT_T *ext);
|
||||
int (*pNSSCSCloseSecretStoreCache) ( void *context,
|
||||
unsigned long ssFlags,
|
||||
SSCS_EXT_T *ext);
|
||||
int (*pNSSCSSetCredential) ( unsigned long ssFlags,
|
||||
SSCS_SECRET_ID_T *appSecretID,
|
||||
SSCS_SECRET_ID_T *sharedSecretID,
|
||||
int credentialType,
|
||||
void *credential,
|
||||
SSCS_EXT_T *ext);
|
||||
|
||||
/* The structure to hold all the possible options
|
||||
* for this PAM module.
|
||||
*/
|
||||
typedef struct options_t
|
||||
{
|
||||
unsigned int debug;
|
||||
}Options;
|
||||
|
||||
#endif
|
||||
|
@ -1,24 +1,57 @@
|
||||
#!/bin/bash
|
||||
# Adding CASA pam entries to pam files.
|
||||
rm -f *.rpmsave
|
||||
for file in "/etc/pam.d/login" "/etc/pam.d/sshd" "/etc/pam.d/xdm" "/etc/pam.d/gdm" "/etc/pam.d/kdm"
|
||||
|
||||
prefix="/etc/pam.d"
|
||||
for auth_file in "$prefix/login" "$prefix/sshd" "$prefix/xdm" "$prefix/gdm" "$prefix/kdm"
|
||||
do
|
||||
if [ -f $file ]
|
||||
if [ -f $auth_file ]
|
||||
then
|
||||
sed -i '/pam_micasa/d' $file
|
||||
var=`grep pam_unix2.so $file`
|
||||
entry=`echo -e "auth\t required\tpam_micasa.so"`
|
||||
if [ "$var" != "" ]
|
||||
sed -i '/pam_micasa/d' $auth_file
|
||||
|
||||
auth_entry=`echo -e "auth\t required\tpam_micasa.so"`
|
||||
|
||||
var1=`grep ^auth.*required.*pam_unix2.so $auth_file`
|
||||
if [ "$var1" != "" ]
|
||||
then
|
||||
sed -i "/^auth.*required.*pam_unix2.so/a$entry" $file
|
||||
sed -i "/^auth.*required.*pam_unix2.so/a$auth_entry" $auth_file
|
||||
continue
|
||||
fi
|
||||
var2=`grep common-auth $file`
|
||||
|
||||
var2=`grep ^auth.*include.*common-auth $auth_file`
|
||||
if [ "$var2" != "" ]
|
||||
then
|
||||
sed -i "/^auth.*include.*common-auth/a$entry" $file
|
||||
sed -i "/^auth.*include.*common-auth/a$auth_entry" $auth_file
|
||||
continue
|
||||
fi
|
||||
sed -i "0,/^auth/s/^\(auth.*\)/\1\n$entry/" $file
|
||||
|
||||
sed -i "0,/^auth/s/^\(auth.*\)/\1\n$auth_entry/" $auth_file
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
for password_file in "$prefix/passwd" "$prefix/gnome-passwd"
|
||||
do
|
||||
if [ -f $password_file ]
|
||||
then
|
||||
sed -i '/pam_micasa/d' $password_file
|
||||
|
||||
passwd_entry=`echo -e "password required\tpam_micasa.so"`
|
||||
|
||||
var1=`grep ^password.*required.*pam_unix2.so $password_file`
|
||||
if [ "$var1" != "" ]
|
||||
then
|
||||
sed -i "/^password.*required.*pam_unix2.so/a$passwd_entry" $password_file
|
||||
continue
|
||||
fi
|
||||
|
||||
var2=`grep ^password.*include.*common-password $password_file`
|
||||
if [ "$var2" != "" ]
|
||||
then
|
||||
sed -i "/^password.*include.*common-password/a$passwd_entry" $password_file
|
||||
continue
|
||||
fi
|
||||
|
||||
sed -i "0,/^password/s/^\(password.*\)/\1\n$passwd_entry/" $password_file
|
||||
fi
|
||||
done
|
||||
|
@ -1,6 +1,8 @@
|
||||
#!/bin/bash
|
||||
# Remove the CASA pam entries from pam files.
|
||||
for pam_file in "/etc/pam.d/login" "/etc/pam.d/sshd" "/etc/pam.d/xdm" "/etc/pam.d/gdm" "/etc/pam.d/kdm"
|
||||
|
||||
prefix="/etc/pam.d"
|
||||
for pam_file in "$prefix/login" "$prefix/sshd" "$prefix/xdm" "$prefix/gdm" "$prefix/kdm" "$prefix/passwd" "$prefix/gnome-passwd"
|
||||
do
|
||||
if [ -f $pam_file ]
|
||||
then
|
||||
|
Loading…
Reference in New Issue
Block a user