diff options
Diffstat (limited to 'source3/auth/user_krb5.c')
-rw-r--r-- | source3/auth/user_krb5.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c new file mode 100644 index 0000000..169bf56 --- /dev/null +++ b/source3/auth/user_krb5.c @@ -0,0 +1,263 @@ +/* + Unix SMB/CIFS implementation. + Authentication utility functions + Copyright (C) Simo Sorce 2010 + + 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/>. +*/ + +#include "includes.h" +#include "auth.h" +#include "librpc/gen_ndr/krb5pac.h" +#include "nsswitch/libwbclient/wbclient.h" +#include "passdb.h" +#include "lib/param/loadparm.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_AUTH + +#ifdef HAVE_KRB5 +NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, + const char *cli_name, + const char *princ_name, + bool *is_mapped, + bool *mapped_to_guest, + char **ntuser, + char **ntdomain, + char **username, + struct passwd **_pw) +{ + NTSTATUS status; + const char *domain = NULL; + const char *realm = NULL; + char *user = NULL; + char *p; + char *fuser = NULL; + char *unixuser = NULL; + struct passwd *pw = NULL; + bool may_retry = false; + + DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name)); + + p = strchr_m(princ_name, '@'); + if (!p) { + DEBUG(3, ("[%s] Doesn't look like a valid principal\n", + princ_name)); + return NT_STATUS_LOGON_FAILURE; + } + + user = talloc_strndup(mem_ctx, princ_name, p - princ_name); + if (!user) { + return NT_STATUS_NO_MEMORY; + } + + realm = p + 1; + + if (!strequal(realm, lp_realm())) { + DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm)); + if (!lp_allow_trusted_domains()) { + return NT_STATUS_LOGON_FAILURE; + } + domain = realm; + } else { + domain = lp_workgroup(); + may_retry = true; + } + + fuser = talloc_asprintf(mem_ctx, + "%s%c%s", + domain, + *lp_winbind_separator(), + user); + if (!fuser) { + return NT_STATUS_NO_MEMORY; + } + + *is_mapped = map_username(mem_ctx, fuser, &fuser); + if (!fuser) { + return NT_STATUS_NO_MEMORY; + } + *mapped_to_guest = false; + + pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true); + if (may_retry && pw == NULL && !*is_mapped) { + fuser = talloc_strdup(mem_ctx, user); + if (!fuser) { + return NT_STATUS_NO_MEMORY; + } + pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true); + } + if (pw) { + if (!unixuser) { + return NT_STATUS_NO_MEMORY; + } + /* if a real user check pam account restrictions */ + /* only really performed if "obey pam restriction" is true */ + /* do this before an eventual mapping to guest occurs */ + status = smb_pam_accountcheck(pw->pw_name, cli_name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("PAM account restrictions prevent user " + "[%s] login\n", unixuser)); + return status; + } + } + if (!pw) { + + /* this was originally the behavior of Samba 2.2, if a user + did not have a local uid but has been authenticated, then + map them to a guest account */ + + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) { + *mapped_to_guest = true; + fuser = talloc_strdup(mem_ctx, lp_guest_account()); + if (!fuser) { + return NT_STATUS_NO_MEMORY; + } + pw = smb_getpwnam(mem_ctx, fuser, &unixuser, false); + } + + /* extra sanity check that the guest account is valid */ + if (!pw) { + DBG_NOTICE("Username %s is invalid on this system\n", + fuser); + return NT_STATUS_LOGON_FAILURE; + } + } + + if (!unixuser) { + return NT_STATUS_NO_MEMORY; + } + + *username = talloc_strdup(mem_ctx, unixuser); + if (!*username) { + return NT_STATUS_NO_MEMORY; + } + *ntuser = user; + *ntdomain = talloc_strdup(mem_ctx, domain); + if (*ntdomain == NULL) { + return NT_STATUS_NO_MEMORY; + } + + *_pw = pw; + + return NT_STATUS_OK; +} + +NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + char *ntuser, + char *ntdomain, + char *username, + struct passwd *pw, + bool mapped_to_guest, bool username_was_mapped, + struct auth_session_info **session_info) +{ + NTSTATUS status; + struct auth_serversupplied_info *server_info; + + if (mapped_to_guest) { + status = make_server_info_guest(mem_ctx, &server_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("make_server_info_guest failed: %s!\n", + nt_errstr(status))); + return status; + } + + } else { + /* + * We didn't get a PAC, we have to make up the user + * ourselves. Try to ask the pdb backend to provide + * SID consistency with ntlmssp session setup + */ + struct samu *sampass; + + sampass = samu_new(talloc_tos()); + if (sampass == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (pdb_getsampwnam(sampass, username)) { + DEBUG(10, ("found user %s in passdb, calling " + "make_server_info_sam\n", username)); + status = make_server_info_sam(mem_ctx, + sampass, + &server_info); + } else { + /* + * User not in passdb, make it up artificially + */ + DEBUG(10, ("didn't find user %s in passdb, calling " + "make_server_info_pw\n", username)); + status = make_server_info_pw(mem_ctx, + username, + pw, + &server_info); + } + + TALLOC_FREE(sampass); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n", + nt_errstr(status))); + return status; + } + + /* make_server_info_pw does not set the domain. Without this + * we end up with the local netbios name in substitutions for + * %D. */ + + if (server_info->info3 != NULL) { + server_info->info3->base.logon_domain.string = + talloc_strdup(server_info->info3, ntdomain); + } + } + + server_info->nss_token |= username_was_mapped; + + status = create_local_token(mem_ctx, server_info, NULL, ntuser, session_info); + talloc_free(server_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("failed to create local token: %s\n", + nt_errstr(status))); + return status; + } + + return NT_STATUS_OK; +} + +#else /* HAVE_KRB5 */ +NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, + const char *cli_name, + const char *princ_name, + bool *is_mapped, + bool *mapped_to_guest, + char **ntuser, + char **ntdomain, + char **username, + struct passwd **_pw) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, + char *ntuser, + char *ntdomain, + char *username, + struct passwd *pw, + bool mapped_to_guest, bool username_was_mapped, + struct auth_session_info **session_info) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +#endif /* HAVE_KRB5 */ |