diff options
author | Günther Deschner <gd@samba.org> | 2006-04-25 12:24:25 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:16:29 -0500 |
commit | 351e749246a278b60a7e18c1eeafdc8ec70efea2 (patch) | |
tree | 7080fbf71b0f4cedfd4eeae1eb42478b2b327b49 | |
parent | 66fd215dc754963c866c3c3402f65d6bd14b8dcd (diff) | |
download | samba-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.in | 2 | ||||
-rw-r--r-- | source3/configure.in | 24 | ||||
-rw-r--r-- | source3/include/ads.h | 12 | ||||
-rw-r--r-- | source3/include/includes.h | 2 | ||||
-rw-r--r-- | source3/libads/kerberos.c | 26 | ||||
-rw-r--r-- | source3/libsmb/clikrb5.c | 98 | ||||
-rw-r--r-- | source3/libsmb/nmblib.c | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cred_cache.c | 1 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_pam.c | 1 |
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) { |