r15240: Correctly disallow unauthorized access when logging on with the
authorGünther Deschner <gd@samba.org>
Tue, 25 Apr 2006 12:24:25 +0000 (12:24 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:16:29 +0000 (11:16 -0500)
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)

source3/Makefile.in
source3/configure.in
source3/include/ads.h
source3/include/includes.h
source3/libads/kerberos.c
source3/libsmb/clikrb5.c
source3/libsmb/nmblib.c
source3/nsswitch/winbindd_cred_cache.c
source3/nsswitch/winbindd_pam.c

index 48a1b10f739096acf8f64ddd7ac8b1aef189cb26..946f74e8a5c4b95715d4f1351e10b72f5fc08a97 100644 (file)
@@ -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...
index c479d2d290f5e914bffa16ee20c2909560628a80..d700740c0d326829b50cc7f89eead70a997f9696 100644 (file)
@@ -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
 
index 2c7999e24fddbb73dc6ef8fe6084654c99f4ad61..711dd2aa70b3ca97b7009893998c53d0b515891b 100644 (file)
@@ -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;
index 944d1b43c026444fc62de1090230128a124b6129..0eb2ba83aab04a6f0a5cbcb02b3b037a34e2b412 100644 (file)
@@ -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 */
index 960709a5f044ae99c5196ac7fd7f9c9f59e114ed..2dfdc31dd56e6fc71405d71223151d25a77c2589 100644 (file)
@@ -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);
 }
 
index d3da25760b8c4f48fba9a111f06aa2159e09ccfd..40ffec6f5328e49e2e52d9e759f466c4cb3a64da 100644 (file)
@@ -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, 
index 4d84d7bc4999bbd7fd4aba5fab1dcf48dd75441a..5280dfdbffabbc9ac335e59f60f2430c620c015f 100644 (file)
@@ -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);
 
index 4c539b9b23a593a9b64637a21d445050f5022e95..eb39d1dafb49af7e4e5ac36f40ec9b9860718c5c 100644 (file)
@@ -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);
 
index d35de4ce41397f6f3f2231928abd84ecbf3d2458..d38bdf3dfa85fbc02d1446c4a6a5bf0a18850908 100644 (file)
@@ -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) {