kdc: Send bad password via NETLOGON in RODC
authorGarming Sam <garming@catalyst.net.nz>
Mon, 3 Apr 2017 23:57:01 +0000 (11:57 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 30 May 2017 06:06:06 +0000 (08:06 +0200)
This means that a RWDC will be collecting the badPwdCount to ensure
domain wide lockout.

TODO The parameters should be better constructed.

Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/kdc/hdb-samba4.c
source4/kdc/wscript_build

index c0d0e24713fe39ca818074debe26a383c2051ba1..81ac60e38ba34d96dbe5478e5fa8f96d1b40a234 100644 (file)
@@ -43,6 +43,8 @@
 #include "dsdb/samdb/samdb.h"
 #include "param/param.h"
 #include "../lib/tsocket/tsocket.h"
+#include "librpc/gen_ndr/ndr_winbind_c.h"
+#include "lib/messaging/irpc.h"
 
 static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode)
 {
@@ -294,6 +296,61 @@ hdb_samba4_check_s4u2self(krb5_context context, HDB *db,
        return ret;
 }
 
+static void send_bad_password_netlogon(TALLOC_CTX *mem_ctx,
+                                      struct samba_kdc_db_context *kdc_db_ctx,
+                                      struct auth_usersupplied_info *user_info)
+{
+       struct dcerpc_binding_handle *irpc_handle;
+       struct winbind_SamLogon req;
+       struct netr_IdentityInfo *identity_info;
+       struct netr_NetworkInfo *network_info;
+
+       irpc_handle = irpc_binding_handle_by_name(mem_ctx, kdc_db_ctx->msg_ctx,
+                                                 "winbind_server",
+                                                 &ndr_table_winbind);
+       if (irpc_handle == NULL) {
+               DEBUG(0, ("Winbind fowarding for [%s]\\[%s] failed, "
+                         "no winbind_server running!\n",
+                         user_info->mapped.domain_name, user_info->mapped.account_name));
+               return;
+       }
+
+       network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
+       if (network_info == NULL) {
+               DEBUG(0, ("Winbind forwarding failed: No memory\n"));
+               return;
+       }
+
+       identity_info = &network_info->identity_info;
+       req.in.logon_level = 2;
+       req.in.logon.network = network_info;
+
+       identity_info->domain_name.string = user_info->mapped.domain_name;
+       identity_info->parameter_control = user_info->logon_parameters; /* TODO */
+       identity_info->logon_id_low = 0;
+       identity_info->logon_id_high = 0;
+       identity_info->account_name.string = user_info->mapped.account_name;
+       identity_info->workstation.string
+               = talloc_asprintf(identity_info, "krb5-bad-pw on RODC from %s",
+                                 tsocket_address_string(user_info->remote_host,
+                                                        identity_info));
+       if (identity_info->workstation.string == NULL) {
+               DEBUG(0, ("Winbind forwarding failed: No memory allocating workstation string\n"));
+               return;
+       }
+
+       req.in.validation_level = 3;
+
+       /* 
+        * The memory in identity_info and user_info only needs to be
+        * valid until the end of this function call, as it will be
+        * pushed to NDR during this call 
+        */
+       
+       dcerpc_winbind_SamLogon_r_send(mem_ctx, kdc_db_ctx->ev_ctx,
+                                      irpc_handle, &req);
+}
+
 static krb5_error_code hdb_samba4_auth_status(krb5_context context, HDB *db,
                                              hdb_entry_ex *entry,
                                              struct sockaddr *from_addr,
@@ -368,13 +425,6 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, HDB *db,
                NTSTATUS status;
                int ret;
 
-               if (hdb_auth_status == HDB_AUTH_WRONG_PASSWORD) {
-                       authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
-                       status = NT_STATUS_WRONG_PASSWORD;
-               } else {
-                       status = NT_STATUS_OK;
-               }
-
                ret = tsocket_address_bsd_from_sockaddr(frame, from_addr,
                                                        sa_socklen,
                                                        &remote_host);
@@ -387,6 +437,21 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, HDB *db,
                ui.mapped.account_name = account_name;
                ui.mapped.domain_name = domain_name;
 
+               if (hdb_auth_status == HDB_AUTH_WRONG_PASSWORD) {
+                       authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
+                       status = NT_STATUS_WRONG_PASSWORD;
+                       /*
+                        * TODO We currently send a bad password via NETLOGON,
+                        * however, it should probably forward the ticket to
+                        * another KDC to allow login after password changes.
+                        */
+                       if (kdc_db_ctx->rodc) {
+                               send_bad_password_netlogon(frame, kdc_db_ctx, &ui);
+                       }
+               } else {
+                       status = NT_STATUS_OK;
+               }
+
                log_authentication_event(kdc_db_ctx->msg_ctx,
                                         kdc_db_ctx->lp_ctx,
                                         &ui,
index 1c54a36bdf8920ce2af44af10cdcd737a2a45ff9..c1f9a478582d2f369a45de59ac0943420f848efa 100644 (file)
@@ -47,7 +47,7 @@ if bld.CONFIG_GET('SAMBA_USES_MITKDC'):
 
 bld.SAMBA_LIBRARY('HDB_SAMBA4',
                   source='hdb-samba4.c hdb-samba4-plugin.c',
-                  deps='ldb auth4_sam common_auth samba-credentials hdb db-glue samba-hostconfig com_err sdb_hdb',
+                  deps='ldb auth4_sam common_auth samba-credentials hdb db-glue samba-hostconfig com_err sdb_hdb RPC_NDR_WINBIND',
                   includes=kdc_include,
                   private_library=True,
                   enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL')