-/* Unix NT password database implementation, version 0.7.5.
- *
- * 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., 675
- * Mass Ave, Cambridge, MA 02139, USA.
+/*
+ Unix SMB/CIFS implementation.
+ Use PAM to update user passwords in the local SAM
+ Copyright (C) Steve Langasek 1998-2003
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+
*/
/* indicate the following groups are defined */
#include "includes.h"
-#ifndef LINUX
+/* This is only used in the Sun implementation. FIXME: we really
+ want a define here that distinguishes between the Solaris PAM
+ and others (including FreeBSD). */
-/* This is only used in the Sun implementation. */
+#ifndef LINUX
+#if defined(HAVE_SECURITY_PAM_APPL_H)
#include <security/pam_appl.h>
+#elif defined(HAVE_PAM_PAM_APPL_H)
+#include <pam/pam_appl.h>
+#endif
+#endif
-#endif /* LINUX */
-
+#if defined(HAVE_SECURITY_PAM_MODULES_H)
#include <security/pam_modules.h>
+#elif defined(HAVE_PAM_PAM_MODULES_H)
+#include <pam/pam_modules.h>
+#endif
#include "general.h"
int smb_update_db( pam_handle_t *pamh, int ctrl, const char *user, const char *pass_new )
{
- char c;
- int retval, i;
- pstring err_str;
- pstring msg_str;
-
- err_str[0] = '\0';
- msg_str[0] = '\0';
-
- retval = local_password_change( user, 0, pass_new, err_str, sizeof(err_str),
- msg_str, sizeof(msg_str) );
-
- if (!retval) {
- if (*err_str) {
- err_str[PSTRING_LEN-1] = '\0';
- make_remark( pamh, ctrl, PAM_ERROR_MSG, err_str );
- }
-
- /* FIXME: what value is appropriate here? */
- retval = PAM_AUTHTOK_ERR;
- } else {
- if (*msg_str) {
- msg_str[PSTRING_LEN-1] = '\0';
- make_remark( pamh, ctrl, PAM_TEXT_INFO, msg_str );
- }
- retval = PAM_SUCCESS;
- }
-
- return retval;
+ int retval;
+ char *err_str = NULL;
+ char *msg_str = NULL;
+
+ retval = NT_STATUS_IS_OK(local_password_change(user, LOCAL_SET_PASSWORD, pass_new,
+ &err_str,
+ &msg_str));
+
+ if (!retval) {
+ if (err_str) {
+ make_remark(pamh, ctrl, PAM_ERROR_MSG, err_str );
+ }
+
+ /* FIXME: what value is appropriate here? */
+ retval = PAM_AUTHTOK_ERR;
+ } else {
+ if (msg_str) {
+ make_remark(pamh, ctrl, PAM_TEXT_INFO, msg_str );
+ }
+ retval = PAM_SUCCESS;
+ }
+ SAFE_FREE(err_str);
+ SAFE_FREE(msg_str);
+ return retval;
}
unsigned int ctrl;
int retval;
- extern BOOL in_client;
-
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass = NULL;
+ void (*oldsig_handler)(int);
const char *user;
- const char *pass_old, *pass_new;
+ char *pass_old;
+ char *pass_new;
/* Samba initialization. */
- setup_logging( "pam_smbpass", False );
- charset_initialise();
- codepage_initialise(lp_client_code_page());
- in_client = True;
+ load_case_tables();
+ lp_set_in_client(True);
- ctrl = set_ctrl(flags, argc, argv);
+ ctrl = set_ctrl(pamh, flags, argc, argv);
/*
* First get the name of a user. No need to do anything if we can't
retval = pam_get_user( pamh, &user, "Username: " );
if (retval != PAM_SUCCESS) {
if (on( SMB_DEBUG, ctrl )) {
- _log_err( LOG_DEBUG, "password: could not identify user" );
+ _log_err(pamh, LOG_DEBUG, "password: could not identify user");
}
return retval;
}
if (on( SMB_DEBUG, ctrl )) {
- _log_err( LOG_DEBUG, "username [%s] obtained", user );
+ _log_err(pamh, LOG_DEBUG, "username [%s] obtained", user);
}
- if (!initialize_password_db(True)) {
- _log_err( LOG_ALERT, "Cannot access samba password database" );
+ if (geteuid() != 0) {
+ _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root.");
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ /* Getting into places that might use LDAP -- protect the app
+ from a SIGPIPE it's not expecting */
+ oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN);
+
+ if (!initialize_password_db(False, NULL)) {
+ _log_err(pamh, LOG_ALERT, "Cannot access samba password database" );
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return PAM_AUTHINFO_UNAVAIL;
}
/* obtain user record */
- pdb_init_sam(&sampass);
- pdb_getsampwnam(sampass,user);
+ if ( !(sampass = samu_new( NULL )) ) {
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
+ return nt_status_to_pam(NT_STATUS_NO_MEMORY);
+ }
- if (sampass == NULL) {
- _log_err( LOG_ALERT, "Failed to find entry for user %s.", user );
+ if (!pdb_getsampwnam(sampass,user)) {
+ _log_err(pamh, LOG_ALERT, "Failed to find entry for user %s.", user);
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return PAM_USER_UNKNOWN;
}
+ if (on( SMB_DEBUG, ctrl )) {
+ _log_err(pamh, LOG_DEBUG, "Located account for %s", user);
+ }
if (flags & PAM_PRELIM_CHECK) {
/*
if (_smb_blankpasswd( ctrl, sampass )) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return PAM_SUCCESS;
}
/* tell user what is happening */
#define greeting "Changing password for "
- Announce = (char *) malloc(sizeof(greeting)+strlen(user));
+ Announce = SMB_MALLOC_ARRAY(char, sizeof(greeting)+strlen(user));
if (Announce == NULL) {
- _log_err(LOG_CRIT, "password: out of memory");
- pdb_free_sam(&sampass);
+ _log_err(pamh, LOG_CRIT, "password: out of memory");
+ TALLOC_FREE(sampass);
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return PAM_BUF_ERR;
}
strncpy( Announce, greeting, sizeof(greeting) );
SAFE_FREE( Announce );
if (retval != PAM_SUCCESS) {
- _log_err( LOG_NOTICE
- , "password - (old) token not obtained" );
- pdb_free_sam(&sampass);
+ _log_err(pamh, LOG_NOTICE,
+ "password - (old) token not obtained");
+ TALLOC_FREE(sampass);
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}
}
pass_old = NULL;
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
} else if (flags & PAM_UPDATE_AUTHTOK) {
-#if 0
- /* We used to return when this flag was set, but that breaks
- password synchronization when /other/ tokens are expired. For
- now, we change the password whenever we're asked. SRL */
- if (flags & PAM_CHANGE_EXPIRED_AUTHTOK) {
- pdb_free_sam(&sampass);
- return PAM_SUCCESS;
- }
-#endif
/*
* obtain the proposed password
*/
*/
if (off( SMB_NOT_SET_PASS, ctrl )) {
- retval = pam_get_item( pamh, PAM_OLDAUTHTOK,
- (const void **)&pass_old );
+ retval = _pam_get_item( pamh, PAM_OLDAUTHTOK,
+ &pass_old );
} else {
- retval = pam_get_data( pamh, _SMB_OLD_AUTHTOK,
- (const void **)&pass_old );
+ retval = _pam_get_data( pamh, _SMB_OLD_AUTHTOK,
+ &pass_old );
if (retval == PAM_NO_MODULE_DATA) {
pass_old = NULL;
retval = PAM_SUCCESS;
}
if (retval != PAM_SUCCESS) {
- _log_err( LOG_NOTICE, "password: user not authenticated" );
- pdb_free_sam(&sampass);
+ _log_err(pamh, LOG_NOTICE, "password: user not authenticated");
+ TALLOC_FREE(sampass);
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}
if (retval != PAM_SUCCESS) {
if (on( SMB_DEBUG, ctrl )) {
- _log_err( LOG_ALERT
- , "password: new password not obtained" );
+ _log_err(pamh, LOG_ALERT,
+ "password: new password not obtained");
}
pass_old = NULL; /* tidy up */
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}
retval = _pam_smb_approve_pass(pamh, ctrl, pass_old, pass_new);
if (retval != PAM_SUCCESS) {
- _log_err(LOG_NOTICE, "new password not acceptable");
+ _log_err(pamh, LOG_NOTICE, "new password not acceptable");
pass_new = pass_old = NULL; /* tidy up */
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}
retval = smb_update_db(pamh, ctrl, user, pass_new);
if (retval == PAM_SUCCESS) {
+ uid_t uid;
+
/* password updated */
- _log_err( LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)"
- , user, pdb_get_uid(sampass), uidtoname( getuid() )
- , getuid() );
- } else {
- _log_err( LOG_ERR, "password change failed for user %s"
- , user );
- }
+ if (!sid_to_uid(pdb_get_user_sid(sampass), &uid)) {
+ _log_err(pamh, LOG_NOTICE,
+ "Unable to get uid for user %s",
+ pdb_get_username(sampass));
+ _log_err(pamh, LOG_NOTICE, "password for (%s) changed by (%s/%d)",
+ user, uidtoname(getuid()), getuid());
+ } else {
+ _log_err(pamh, LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)",
+ user, uid, uidtoname(getuid()), getuid());
+ }
+ } else {
+ _log_err(pamh, LOG_ERR, "password change failed for user %s", user);
+ }
pass_old = pass_new = NULL;
if (sampass) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
sampass = NULL;
}
} else { /* something has broken with the library */
- _log_err( LOG_ALERT, "password received unknown request" );
+ _log_err(pamh, LOG_ALERT, "password received unknown request");
retval = PAM_ABORT;
}
if (sampass) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
sampass = NULL;
}
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
+ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}