summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2006-04-25 12:24:25 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:16:29 -0500
commit351e749246a278b60a7e18c1eeafdc8ec70efea2 (patch)
tree7080fbf71b0f4cedfd4eeae1eb42478b2b327b49
parent66fd215dc754963c866c3c3402f65d6bd14b8dcd (diff)
downloadsamba-351e749246a278b60a7e18c1eeafdc8ec70efea2.tar.gz
samba-351e749246a278b60a7e18c1eeafdc8ec70efea2.tar.bz2
samba-351e749246a278b60a7e18c1eeafdc8ec70efea2.zip
r15240: Correctly disallow unauthorized access when logging on with the
kerberized pam_winbind and workstation restrictions are in effect. The krb5 AS-REQ needs to add the host netbios-name in the address-list. We don't get the clear NT_STATUS_INVALID_WORKSTATION code back yet from the edata of the KRB_ERROR but the login at least fails when the local machine is not in the workstation list on the DC. Guenther (This used to be commit 8b2ba11508e2730aba074d7c095291fac2a62176)
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/configure.in24
-rw-r--r--source3/include/ads.h12
-rw-r--r--source3/include/includes.h2
-rw-r--r--source3/libads/kerberos.c26
-rw-r--r--source3/libsmb/clikrb5.c98
-rw-r--r--source3/libsmb/nmblib.c2
-rw-r--r--source3/nsswitch/winbindd_cred_cache.c1
-rw-r--r--source3/nsswitch/winbindd_pam.c1
9 files changed, 164 insertions, 4 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 48a1b10f73..946f74e8a5 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -758,7 +758,7 @@ NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \
libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \
libads/kerberos_verify.o $(SECRETS_OBJ) $(SERVER_MUTEX_OBJ) \
libads/authdata.o $(RPC_PARSE_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
- $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o
+ $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o $(LIBNMB_OBJ)
######################################################################
# now the rules...
diff --git a/source3/configure.in b/source3/configure.in
index c479d2d290..d700740c0d 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -3655,6 +3655,18 @@ if test x"$with_ads_support" != x"no"; then
[Whether krb5_keytab_entry has keyblock member])
fi
+ AC_CACHE_CHECK([for magic in krb5_address],
+ samba_cv_HAVE_MAGIC_IN_KRB5_ADDRESS,[
+ AC_TRY_COMPILE([#include <krb5.h>],
+ [krb5_address addr; addr.magic = 0;],
+ samba_cv_HAVE_MAGIC_IN_KRB5_ADDRESS=yes,
+ samba_cv_HAVE_MAGIC_IN_KRB5_ADDRESS=no)])
+
+ if test x"$samba_cv_HAVE_MAGIC_IN_KRB5_ADDRESS" = x"yes"; then
+ AC_DEFINE(HAVE_MAGIC_IN_KRB5_ADDRESS,1,
+ [Whether the krb5_address struct has a magic property])
+ fi
+
if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" = x"yes"; then
AC_DEFINE(HAVE_KRB5,1,[Whether to have KRB5 support])
AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support])
@@ -3705,6 +3717,18 @@ if test x"$with_ads_support" != x"no"; then
[Whether krb5_princ_realm returns krb5_realm or krb5_data])
fi
+ AC_CACHE_CHECK([for krb5_addresses type],
+ samba_cv_HAVE_KRB5_ADDRESSES,[
+ AC_TRY_COMPILE([#include <krb5.h>],
+ [krb5_addresses addr;],
+ samba_cv_HAVE_KRB5_ADDRESSES=yes,
+ samba_cv_HAVE_KRB5_ADDRESSES=no)])
+
+ if test x"$samba_cv_HAVE_KRB5_ADDRESSES" = x"yes"; then
+ AC_DEFINE(HAVE_KRB5_ADDRESSES,1,
+ [Whether the type krb5_addresses type exists])
+ fi
+
LIBS="$ac_save_LIBS"
fi
diff --git a/source3/include/ads.h b/source3/include/ads.h
index 2c7999e24f..711dd2aa70 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -266,3 +266,15 @@ typedef void **ADS_MODLIST;
#define WELL_KNOWN_GUID_COMPUTERS "AA312825768811D1ADED00C04FD8D5CD"
#define WELL_KNOWN_GUID_USERS "A9D1CA15768811D1ADED00C04FD8D5CD"
+
+#ifndef KRB5_ADDR_NETBIOS
+#define KRB5_ADDR_NETBIOS 0x14
+#endif
+
+typedef struct {
+#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */
+ krb5_address **addrs;
+#else /* Heimdal has the krb5_addresses type */
+ krb5_addresses *addrs;
+#endif
+} smb_krb5_addresses;
diff --git a/source3/include/includes.h b/source3/include/includes.h
index 944d1b43c0..0eb2ba83aa 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -1538,6 +1538,8 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
PAC_LOGON_INFO *get_logon_info_from_pac(PAC_DATA *pac_data);
krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, const char *client_string, const char *service_string, time_t *new_start_time);
krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code);
+krb5_error_code smb_krb5_gen_netbios_krb5_address(smb_krb5_addresses **kerb_addr);
+krb5_error_code smb_krb5_free_addresses(krb5_context context, smb_krb5_addresses *addr);
NTSTATUS krb5_to_nt_status(krb5_error_code kerberos_error);
krb5_error_code nt_status_to_krb5(NTSTATUS nt_status);
#endif /* HAVE_KRB5 */
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 960709a5f0..2dfdc31dd5 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -65,6 +65,7 @@ int kerberos_kinit_password_ext(const char *principal,
time_t *renew_till_time,
const char *cache_name,
BOOL request_pac,
+ BOOL add_netbios_addr,
time_t renewable_time)
{
krb5_context ctx = NULL;
@@ -73,6 +74,7 @@ int kerberos_kinit_password_ext(const char *principal,
krb5_principal me;
krb5_creds my_creds;
krb5_get_init_creds_opt opt;
+ smb_krb5_addresses *addr = NULL;
initialize_krb5_error_table();
if ((code = krb5_init_context(&ctx)))
@@ -101,19 +103,36 @@ int kerberos_kinit_password_ext(const char *principal,
if (request_pac) {
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
- krb5_get_init_creds_opt_set_pac_request(ctx, &opt, True);
+ code = krb5_get_init_creds_opt_set_pac_request(ctx, &opt, True);
+ if (code) {
+ krb5_free_principal(ctx, me);
+ krb5_free_context(ctx);
+ return code;
+ }
#endif
}
+ if (add_netbios_addr) {
+ code = smb_krb5_gen_netbios_krb5_address(&addr);
+ if (code) {
+ krb5_free_principal(ctx, me);
+ krb5_free_context(ctx);
+ return code;
+ }
+ krb5_get_init_creds_opt_set_address_list(&opt, addr->addrs);
+ }
+
if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password),
kerb_prompter, NULL, 0, NULL, &opt)))
{
+ smb_krb5_free_addresses(ctx, addr);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
return code;
}
if ((code = krb5_cc_initialize(ctx, cc, me))) {
+ smb_krb5_free_addresses(ctx, addr);
krb5_free_cred_contents(ctx, &my_creds);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
@@ -122,6 +141,7 @@ int kerberos_kinit_password_ext(const char *principal,
if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {
krb5_cc_close(ctx, cc);
+ smb_krb5_free_addresses(ctx, addr);
krb5_free_cred_contents(ctx, &my_creds);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
@@ -137,6 +157,7 @@ int kerberos_kinit_password_ext(const char *principal,
}
krb5_cc_close(ctx, cc);
+ smb_krb5_free_addresses(ctx, addr);
krb5_free_cred_contents(ctx, &my_creds);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
@@ -178,7 +199,7 @@ int ads_kinit_password(ADS_STRUCT *ads)
}
ret = kerberos_kinit_password_ext(s, ads->auth.password, ads->auth.time_offset,
- &ads->auth.expire, NULL, NULL, False, ads->auth.renewable);
+ &ads->auth.expire, NULL, NULL, False, False, ads->auth.renewable);
if (ret) {
DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
@@ -812,6 +833,7 @@ int kerberos_kinit_password(const char *principal,
0,
cache_name,
False,
+ False,
0);
}
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index d3da25760b..40ffec6f53 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -1205,6 +1205,104 @@ done:
}
+ krb5_error_code smb_krb5_free_addresses(krb5_context context, smb_krb5_addresses *addr)
+{
+ krb5_error_code ret = 0;
+#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */
+ krb5_free_addresses(context, addr->addrs);
+#elif defined(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS) /* Heimdal */
+ ret = krb5_free_addresses(context, addr->addrs);
+ SAFE_FREE(addr->addrs);
+#endif
+ SAFE_FREE(addr);
+ addr = NULL;
+ return ret;
+}
+
+ krb5_error_code smb_krb5_gen_netbios_krb5_address(smb_krb5_addresses **kerb_addr)
+{
+ krb5_error_code ret = 0;
+ nstring buf;
+#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */
+ krb5_address **addrs = NULL;
+#elif defined(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS) /* Heimdal */
+ krb5_addresses *addrs = NULL;
+#endif
+
+ *kerb_addr = (smb_krb5_addresses *)SMB_MALLOC(sizeof(smb_krb5_addresses));
+ if (*kerb_addr == NULL) {
+ return ENOMEM;
+ }
+
+ put_name(buf, global_myname(), ' ', 0x20);
+
+#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */
+ {
+ int num_addr = 2;
+
+ addrs = (krb5_address **)SMB_MALLOC(sizeof(krb5_address *) * num_addr);
+ if (addrs == NULL) {
+ return ENOMEM;
+ }
+
+ memset(addrs, 0, sizeof(krb5_address *) * num_addr);
+
+ addrs[0] = (krb5_address *)SMB_MALLOC(sizeof(krb5_address));
+ if (addrs[0] == NULL) {
+ SAFE_FREE(addrs);
+ return ENOMEM;
+ }
+
+ addrs[0]->magic = KV5M_ADDRESS;
+ addrs[0]->addrtype = KRB5_ADDR_NETBIOS;
+ addrs[0]->length = MAX_NETBIOSNAME_LEN;
+ addrs[0]->contents = (unsigned char *)SMB_MALLOC(addrs[0]->length);
+ if (addrs[0]->contents == NULL) {
+ SAFE_FREE(addrs[0]);
+ SAFE_FREE(addrs);
+ return ENOMEM;
+ }
+
+ memcpy(addrs[0]->contents, buf, addrs[0]->length);
+
+ addrs[1] = NULL;
+ }
+#elif defined(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS) /* Heimdal */
+ {
+ addrs = (krb5_addresses *)SMB_MALLOC(sizeof(krb5_addresses));
+ if (addrs == NULL) {
+ return ENOMEM;
+ }
+
+ memset(addrs, 0, sizeof(krb5_addresses));
+
+ addrs->len = 1;
+ addrs->val = (krb5_address *)SMB_MALLOC(sizeof(krb5_address));
+ if (addrs->val == NULL) {
+ SAFE_FREE(addrs);
+ return ENOMEM;
+ }
+
+ addrs->val[0].addr_type = KRB5_ADDR_NETBIOS;
+ addrs->val[0].address.length = MAX_NETBIOSNAME_LEN;
+ addrs->val[0].address.data = (unsigned char *)SMB_MALLOC(addrs->val[0].address.length);
+ if (addrs->val[0].address.data == NULL) {
+ SAFE_FREE(addrs->val);
+ SAFE_FREE(addrs);
+ return ENOMEM;
+ }
+
+ memcpy(addrs->val[0].address.data, buf, addrs->val[0].address.length);
+ }
+#else
+#error UNKNOWN_KRB5_ADDRESS_FORMAT
+#endif
+ (*kerb_addr)->addrs = addrs;
+
+ return ret;
+}
+
+
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index 4d84d7bc49..5280dfdbff 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -265,7 +265,7 @@ static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
[15 bytes name + padding][1 byte name type].
****************************************************************************/
-static void put_name(char *dest, const char *name, int pad, unsigned int name_type)
+void put_name(char *dest, const char *name, int pad, unsigned int name_type)
{
size_t len = strlen(name);
diff --git a/source3/nsswitch/winbindd_cred_cache.c b/source3/nsswitch/winbindd_cred_cache.c
index 4c539b9b23..eb39d1dafb 100644
--- a/source3/nsswitch/winbindd_cred_cache.c
+++ b/source3/nsswitch/winbindd_cred_cache.c
@@ -113,6 +113,7 @@ static void krb5_ticket_refresh_handler(struct timed_event *te,
&entry->renew_until,
entry->ccname,
False, /* no PAC required anymore */
+ True,
WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
seteuid(0);
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index d35de4ce41..d38bdf3dfa 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -489,6 +489,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
&renewal_until,
cc,
True,
+ True,
WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
if (krb5_ret) {