wb-ndr: implement WINBIND_TRUST_LEVEL_COMPAT_CHECK_MACHCC
authorStefan Metzmacher <metze@sernet.de>
Wed, 5 Mar 2008 10:03:38 +0000 (11:03 +0100)
committerStefan Metzmacher <metze@sernet.de>
Fri, 2 May 2008 14:13:26 +0000 (16:13 +0200)
metze

source/winbindd/winbindd_misc.c

index 4e4154adc593e0662aa26a88bed9077c8b7acebe..d4a93f0bb1054bf166a95fe91827cdcb6edb3e76 100644 (file)
@@ -293,6 +293,69 @@ static void ndr_child_trust_compat_list(struct winbindd_domain *domain,
        r->out.result = WINBIND_STATUS_OK;
 }
 
+static void ndr_child_trust_compat_check_machcc(struct winbindd_domain *domain,
+                                               struct winbindd_cli_state *state,
+                                               struct winbind_trust *r)
+{
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       int num_retries = 0;
+       struct winbindd_domain *contact_domain;
+
+       DEBUG(3, ("check machine account\n"));
+
+       /* Get trust account password */
+
+ again:
+
+       contact_domain = find_our_domain();
+
+        /* This call does a cli_nt_setup_creds() which implicitly checks
+           the trust account password. */
+
+       invalidate_cm_connection(&contact_domain->conn);
+
+       {
+               struct rpc_pipe_client *netlogon_pipe;
+               result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
+       }
+
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
+               goto done;
+       }
+
+       /* There is a race condition between fetching the trust account
+          password and the periodic machine password change.  So it's
+          possible that the trust account password has been changed on us.
+          We are returned NT_STATUS_ACCESS_DENIED if this happens. */
+
+#define MAX_RETRIES 8
+
+        if ((num_retries < MAX_RETRIES) &&
+           NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
+               num_retries++;
+               goto again;
+        }
+
+       /* Pass back result code - zero for success, other values for
+          specific failures. */
+
+       DEBUG(3,("secret is %s\n", NT_STATUS_IS_OK(result) ?
+               "good" : "bad"));
+
+ done:
+
+       DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
+             ("Checking the trust account password returned %s\n",
+              nt_errstr(result)));
+
+       if (NT_STATUS_IS_OK(result)) {
+               r->out.result = WINBIND_STATUS_OK;
+       } else {
+               r->out.result = WINBIND_STATUS_FOOBAR;
+       }
+}
+
 void winbindd_ndr_domain_child_trust(struct winbindd_domain *domain,
                                     struct winbindd_cli_state *state)
 {
@@ -305,6 +368,9 @@ void winbindd_ndr_domain_child_trust(struct winbindd_domain *domain,
        case WINBIND_TRUST_LEVEL_COMPAT_LIST:
                ndr_child_trust_compat_list(domain, state, r);
                return;
+       case WINBIND_TRUST_LEVEL_COMPAT_CHECK_MACHCC:
+               ndr_child_trust_compat_check_machcc(domain, state, r);
+               return;
        }
 
        r->out.result = WINBIND_STATUS_UNKNOWN_LEVEL;