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
+ 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,
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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "auth/auth.h"
-#include "system/passwd.h"
+#include "system/passwd.h" /* needed by some systems for struct passwd */
+#include "lib/socket/socket.h"
+#include "auth/pam_errors.h"
+#include "param/param.h"
/* TODO: look at how to best fill in parms retrieveing a struct passwd info
* except in case USER_INFO_DONT_CHECK_UNIX_ACCOUNT is set
*/
static NTSTATUS authunix_make_server_info(TALLOC_CTX *mem_ctx,
const struct auth_usersupplied_info *user_info,
+ struct passwd *pwd,
struct auth_serversupplied_info **_server_info)
{
struct auth_serversupplied_info *server_info;
+ NTSTATUS status;
- server_info = talloc(mem_ctx, struct auth_serversupplied_info);
- NT_STATUS_HAVE_NO_MEMORY(server_info);
-
- server_info->authenticated = True;
-
- server_info->account_name = talloc_strdup(server_info, talloc_strdup(mem_ctx, user_info->account_name));
- NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
-
- server_info->domain_name = talloc_strdup(server_info, talloc_strdup(mem_ctx, "unix"));
- NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
-
+ /* This is a real, real hack */
+ if (pwd->pw_uid == 0) {
+ status = auth_system_server_info(mem_ctx, &server_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- /* is this correct? */
- server_info->account_sid = NULL;
- server_info->primary_group_sid = NULL;
- server_info->n_domain_groups = 0;
- server_info->domain_groups = NULL;
+ server_info->account_name = talloc_steal(server_info, pwd->pw_name);
+ NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
+
+ server_info->domain_name = talloc_strdup(server_info, "unix");
+ NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
+ } else {
+ server_info = talloc(mem_ctx, struct auth_serversupplied_info);
+ NT_STATUS_HAVE_NO_MEMORY(server_info);
+
+ server_info->authenticated = True;
+
+ server_info->account_name = talloc_steal(server_info, pwd->pw_name);
+ NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
+
+ server_info->domain_name = talloc_strdup(server_info, "unix");
+ NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
+
+ /* This isn't in any way correct.. */
+ server_info->account_sid = NULL;
+ server_info->primary_group_sid = NULL;
+ server_info->n_domain_groups = 0;
+ server_info->domain_groups = NULL;
+ }
server_info->user_session_key = data_blob(NULL,0);
server_info->lm_session_key = data_blob(NULL,0);
- server_info->full_name = talloc_strdup(server_info, "");
+ server_info->full_name = talloc_steal(server_info, pwd->pw_gecos);
NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
server_info->logon_script = talloc_strdup(server_info, "");
NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
return NT_STATUS_OK;
}
+static NTSTATUS talloc_getpwnam(TALLOC_CTX *ctx, const char *username, struct passwd **pws)
+{
+ struct passwd *ret;
+ struct passwd *from;
+
+ *pws = NULL;
+
+ ret = talloc(ctx, struct passwd);
+ NT_STATUS_HAVE_NO_MEMORY(ret);
+
+ from = getpwnam(username);
+ if (!from) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ ret->pw_name = talloc_strdup(ctx, from->pw_name);
+ NT_STATUS_HAVE_NO_MEMORY(ret->pw_name);
+
+ ret->pw_passwd = talloc_strdup(ctx, from->pw_passwd);
+ NT_STATUS_HAVE_NO_MEMORY(ret->pw_passwd);
+
+ ret->pw_uid = from->pw_uid;
+ ret->pw_gid = from->pw_gid;
+ ret->pw_gecos = talloc_strdup(ctx, from->pw_gecos);
+ NT_STATUS_HAVE_NO_MEMORY(ret->pw_gecos);
+
+ ret->pw_dir = talloc_strdup(ctx, from->pw_dir);
+ NT_STATUS_HAVE_NO_MEMORY(ret->pw_dir);
+
+ ret->pw_shell = talloc_strdup(ctx, from->pw_shell);
+ NT_STATUS_HAVE_NO_MEMORY(ret->pw_shell);
+
+ *pws = ret;
+
+ return NT_STATUS_OK;
+}
+
+
#ifdef HAVE_SECURITY_PAM_APPL_H
#include <security/pam_appl.h>
(*reply)[num].resp_retcode = PAM_SUCCESS;
(*reply)[num].resp = NULL;
DEBUG(4,("PAM Info message in conversation function: %s\n", (msg[num]->msg)));
+ break;
case PAM_ERROR_MSG:
(*reply)[num].resp_retcode = PAM_SUCCESS;
break;
default:
+ while (num > 0) {
+ SAFE_FREE((*reply)[num-1].resp);
+ num--;
+ }
SAFE_FREE(*reply);
*reply = NULL;
DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n"));
static NTSTATUS smb_pam_start(pam_handle_t **pamh, const char *account_name, const char *remote_host, struct pam_conv *pconv)
{
- NTSTATUS nt_status;
int pam_error;
if (account_name == NULL || remote_host == NULL) {
DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", remote_host));
pam_error = pam_set_item(*pamh, PAM_RHOST, remote_host);
if (pam_error != PAM_SUCCESS) {
+ NTSTATUS nt_status;
+
DEBUG(4,("smb_pam_start: setting rhost failed with error: %s\n",
pam_strerror(*pamh, pam_error)));
nt_status = pam_to_nt_status(pam_error);
DEBUG(4,("smb_pam_start: PAM: setting tty\n"));
pam_error = pam_set_item(*pamh, PAM_TTY, "samba");
if (pam_error != PAM_SUCCESS) {
+ NTSTATUS nt_status;
+
DEBUG(4,("smb_pam_start: setting tty failed with error: %s\n",
pam_strerror(*pamh, pam_error)));
nt_status = pam_to_nt_status(pam_error);
pam_error = pam_authenticate(pamh, PAM_SILENT | lp_null_passwords() ? 0 : PAM_DISALLOW_NULL_AUTHTOK);
switch( pam_error ){
case PAM_AUTH_ERR:
- DEBUG(2, ("smb_pam_auth: PAM: Athentication Error for user %s\n", user));
+ DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user));
break;
case PAM_CRED_INSUFFICIENT:
DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user));
return pam_to_nt_status(pam_error);
}
-static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersupplied_info *user_info)
+static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersupplied_info *user_info, struct passwd **pws)
{
struct smb_pam_user_info *info;
struct pam_conv *pamconv;
return NT_STATUS_NO_MEMORY;
}
- info->account_name = user_info->account_name;
- info->plaintext_password = (char *)(user_info->plaintext_password.data);
+ info->account_name = user_info->mapped.account_name;
+ info->plaintext_password = user_info->password.plaintext;
pamconv = talloc(ctx, struct pam_conv);
if (pamconv == NULL) {
* if true set up a crack name routine.
*/
- nt_status = smb_pam_start(&pamh, user_info->account_name, user_info->remote_host, pamconv);
+ nt_status = smb_pam_start(&pamh, user_info->mapped.account_name, user_info->remote_host ? user_info->remote_host->addr : NULL, pamconv);
if (!NT_STATUS_IS_OK(nt_status)) {
- smb_pam_end(pamh);
return nt_status;
}
- nt_status = smb_pam_auth(pamh, user_info->account_name);
+ nt_status = smb_pam_auth(pamh, user_info->mapped.account_name);
if (!NT_STATUS_IS_OK(nt_status)) {
smb_pam_end(pamh);
return nt_status;
if ( ! (user_info->flags & USER_INFO_DONT_CHECK_UNIX_ACCOUNT)) {
- nt_status = smb_pam_account(pamh, user_info->account_name);
+ nt_status = smb_pam_account(pamh, user_info->mapped.account_name);
if (!NT_STATUS_IS_OK(nt_status)) {
smb_pam_end(pamh);
return nt_status;
}
- nt_status = smb_pam_setcred(pamh, user_info->account_name);
+ nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name);
if (!NT_STATUS_IS_OK(nt_status)) {
smb_pam_end(pamh);
return nt_status;
}
smb_pam_end(pamh);
- return NT_STATUS_OK;
-}
-
-#else
-static NTSTATUS talloc_getpwnam(TALLOC_CTX *ctx, char *username, struct passwd **pws)
-{
- struct passwd *ret;
- struct passwd *from;
-
- *pws = NULL;
-
- ret = talloc(ctx, struct passwd);
- NT_STATUS_HAVE_NO_MEMORY(ret);
-
- from = getpwnam(username);
- if (!from) {
- return NT_STATUS_NO_SUCH_USER;
+ nt_status = talloc_getpwnam(ctx, user_info->mapped.account_name, pws);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
}
- ret->pw_name = talloc_strdup(ctx, from->pw_name);
- NT_STATUS_HAVE_NO_MEMORY(ret->pw_name);
-
- ret->pw_passwd = talloc_strdup(ctx, from->pw_passwd);
- NT_STATUS_HAVE_NO_MEMORY(ret->pw_passwd);
-
- ret->pw_uid = from->pw_uid;
- ret->pw_gid = from->pw_gid;
- ret->pw_gecos = talloc_strdup(ctx, from->pw_gecos);
- NT_STATUS_HAVE_NO_MEMORY(ret->pw_gecos);
-
- ret->pw_dir = talloc_strdup(ctx, from->pw_dir);
- NT_STATUS_HAVE_NO_MEMORY(ret->pw_dir);
-
- ret->pw_shell = talloc_strdup(ctx, from->pw_shell);
- NT_STATUS_HAVE_NO_MEMORY(ret->pw_shell);
-
- *pws = ret;
-
- return NT_STATUS_OK;
+ return NT_STATUS_OK;
}
+#else
/****************************************************************************
core of password checking routine
#endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
}
-/**
- Does a string have any lowercase chars in it?
-**/
-static BOOL strhaslower(const char *s)
-{
- while (*s) {
- if (islower(*s)) return True;
- s++;
- }
- return False;
-}
-
-/**
- Does a string have any uppercase chars in it?
-**/
-static BOOL strhasupper(const char *s)
-{
- while (*s) {
- if (isupper(*s)) return True;
- s++;
- }
- return False;
-}
-
-static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersupplied_info *user_info)
+static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersupplied_info *user_info, struct passwd **ret_passwd)
{
char *username;
char *password;
NTSTATUS nt_status;
int level = lp_passwordlevel();
- username = talloc_strdup(ctx, user_info->account_name);
- password = talloc_strdup(ctx, user_info->plaintext_password.data);
+ *ret_passwd = NULL;
+
+ username = talloc_strdup(ctx, user_info->mapped.account_name);
+ password = talloc_strdup(ctx, user_info->password.plaintext);
nt_status = talloc_getpwnam(ctx, username, &pws);
if (!NT_STATUS_IS_OK(nt_status)) {
}
if (password == NULL) {
DEBUG(3, ("Allowing access to %s with null password\n", username));
+ *ret_passwd = pws;
return NT_STATUS_OK;
}
}
/* try it as it came to us */
nt_status = password_check(username, password, crypted, salt);
- if NT_STATUS_IS_OK(nt_status) {
+ if (NT_STATUS_IS_OK(nt_status)) {
+ *ret_passwd = pws;
return nt_status;
}
else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
strlower(pwcopy);
nt_status = password_check(username, pwcopy, crypted, salt);
if NT_STATUS_IS_OK(nt_status) {
+ *ret_passwd = pws;
return nt_status;
}
}
#if 0
if (NT_STATUS_IS_OK(nt_status = string_combinations(pwcopy, password_check, level))) {
+ *ret_passwd = pws;
return nt_status;
}
#endif
*
**/
+static NTSTATUS authunix_want_check(struct auth_method_context *ctx,
+ TALLOC_CTX *mem_ctx,
+ const struct auth_usersupplied_info *user_info)
+{
+ if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ return NT_STATUS_OK;
+}
+
static NTSTATUS authunix_check_password(struct auth_method_context *ctx,
TALLOC_CTX *mem_ctx,
const struct auth_usersupplied_info *user_info,
- struct auth_serversupplied_info **server_info)
+ struct auth_serversupplied_info **server_info)
{
TALLOC_CTX *check_ctx;
NTSTATUS nt_status;
+ struct passwd *pwd;
- if (! user_info->account_name && ! *user_info->account_name) {
+ if (user_info->password_state != AUTH_PASSWORD_PLAIN) {
return NT_STATUS_INVALID_PARAMETER;
}
return NT_STATUS_NO_MEMORY;
}
- nt_status = check_unix_password(check_ctx, user_info);
- if ( ! NT_STATUS_IS_OK(nt_status)) {
+ nt_status = check_unix_password(check_ctx, user_info, &pwd);
+ if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(check_ctx);
return nt_status;
}
- nt_status = authunix_make_server_info(mem_ctx, user_info, server_info);
- if ( ! NT_STATUS_IS_OK(nt_status)) {
+ nt_status = authunix_make_server_info(mem_ctx, user_info, pwd, server_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(check_ctx);
return nt_status;
}
static const struct auth_operations unix_ops = {
.name = "unix",
.get_challenge = auth_get_challenge_not_implemented,
- .check_password = authunix_check_password
+ .want_check = authunix_want_check,
+ .check_password = authunix_check_password
};
NTSTATUS auth_unix_init(void)