r23792: convert Samba4 to GPLv3
[kai/samba-autobuild/.git] / source4 / libnet / libnet_vampire.c
index 2e93a459661026439d15397d14677ab23d0c0b3d..d015a07730e41d81e4739d76ff30056e2be337f0 100644 (file)
@@ -7,7 +7,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 
 #include "includes.h"
 #include "libnet/libnet.h"
+#include "libcli/auth/libcli_auth.h"
+#include "auth/gensec/gensec.h"
+#include "auth/credentials/credentials.h"
+#include "auth/gensec/schannel_proto.h"
 #include "librpc/gen_ndr/ndr_netlogon.h"
-#include "librpc/gen_ndr/ndr_samr.h"
-#include "dlinklist.h"
-
-struct samsync_secret {
-       struct samsync_secret *prev, *next;
-       DATA_BLOB secret;
-       char *name;
-       NTTIME mtime;
-};
-
-struct samsync_trusted_domain {
-       struct samsync_trusted_domain *prev, *next;
-        struct dom_sid *sid;
-       char *name;
-};
-
-struct samdump_state {
-       struct samsync_secret *secrets;
-       struct samsync_trusted_domain *trusted_domains;
-};
+#include "librpc/gen_ndr/ndr_netlogon_c.h"
 
 
 /**
@@ -53,6 +37,7 @@ struct samdump_state {
  */
 static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
                         struct creds_CredentialState *creds,
+                        bool rid_crypt,
                         enum netr_SamDatabaseID database,
                         struct netr_DELTA_ENUM *delta,
                         char **error_string) 
@@ -65,14 +50,16 @@ static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
        const char *username = user->account_name.string;
        NTSTATUS nt_status;
 
-       if (user->lm_password_present) {
-               sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0);
-               user->lmpassword = lm_hash;
-       }
-
-       if (user->nt_password_present) {
-               sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0);
-               user->ntpassword = nt_hash;
+       if (rid_crypt) {
+               if (user->lm_password_present) {
+                       sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0);
+                       user->lmpassword = lm_hash;
+               }
+               
+               if (user->nt_password_present) {
+                       sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0);
+                       user->ntpassword = nt_hash;
+               }
        }
 
        if (user->user_private_info.SensitiveData) {
@@ -87,17 +74,26 @@ static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
                nt_status = ndr_pull_struct_blob(&data, mem_ctx, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
                if (NT_STATUS_IS_OK(nt_status)) {
                        if (keys.keys.keys2.lmpassword.length == 16) {
-                               sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0);
-                               user->lmpassword = lm_hash;
+                               if (rid_crypt) {
+                                       sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0);
+                                       user->lmpassword = lm_hash;
+                               } else {
+                                       user->lmpassword = keys.keys.keys2.lmpassword.pwd;
+                               }
                                user->lm_password_present = True;
                        }
                        if (keys.keys.keys2.ntpassword.length == 16) {
-                               sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0);
-                               user->ntpassword = nt_hash;
+                               if (rid_crypt) {
+                                       sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0);
+                                       user->ntpassword = nt_hash;
+                               } else {
+                                       user->ntpassword = keys.keys.keys2.ntpassword.pwd;
+                               }
                                user->nt_password_present = True;
                        }
+                       /* TODO: rid decrypt history fields */
                } else {
-                       *error_string = talloc_asprintf(mem_ctx, "Failed to parse Sensitive Data for %s:\n", username);
+                       *error_string = talloc_asprintf(mem_ctx, "Failed to parse Sensitive Data for %s:", username);
                        dump_data(10, data.data, data.length);
                        return nt_status;
                }
@@ -133,6 +129,7 @@ static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx,
 
 static NTSTATUS fix_delta(TALLOC_CTX *mem_ctx,                 
                          struct creds_CredentialState *creds,
+                         bool rid_crypt,
                          enum netr_SamDatabaseID database,
                          struct netr_DELTA_ENUM *delta,
                          char **error_string)
@@ -144,6 +141,7 @@ static NTSTATUS fix_delta(TALLOC_CTX *mem_ctx,
        {
                nt_status = fix_user(mem_ctx, 
                                     creds,
+                                    rid_crypt,
                                     database,
                                     delta,
                                     error_string);
@@ -164,80 +162,164 @@ static NTSTATUS fix_delta(TALLOC_CTX *mem_ctx,
        return nt_status;
 }
 
-static NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamSync *r)
+NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamSync *r)
 {
        NTSTATUS nt_status, dbsync_nt_status;
-       TALLOC_CTX *loop_ctx, *delta_ctx;
+       TALLOC_CTX *samsync_ctx, *loop_ctx, *delta_ctx;
        struct creds_CredentialState *creds;
        struct netr_DatabaseSync dbsync;
        struct cli_credentials *machine_account;
-       struct dcerpc_binding *b;
        struct dcerpc_pipe *p;
+       struct libnet_context *machine_net_ctx;
+       struct libnet_RpcConnect *c;
+       struct libnet_SamSync_state *state;
        const enum netr_SamDatabaseID database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS}; 
        int i;
 
-       /* TODO: This is bogus */
-       const char **bindings = lp_passwordserver();
-       const char *binding;
-
-       if (bindings && bindings[0]) {
-               binding = bindings[0];
-       }
+       samsync_ctx = talloc_named(mem_ctx, 0, "SamSync top context");
 
-       machine_account = cli_credentials_init(mem_ctx);
-       if (!machine_account) {
-               return NT_STATUS_NO_MEMORY;
+       if (!r->in.machine_account) { 
+               machine_account = cli_credentials_init(samsync_ctx);
+               if (!machine_account) {
+                       talloc_free(samsync_ctx);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               cli_credentials_set_conf(machine_account);
+               nt_status = cli_credentials_set_machine_account(machine_account);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       r->out.error_string = talloc_strdup(mem_ctx, "Could not obtain machine account password - are we joined to the domain?");
+                       talloc_free(samsync_ctx);
+                       return nt_status;
+               }
+       } else {
+               machine_account = r->in.machine_account;
        }
 
-       cli_credentials_set_conf(machine_account);
-       nt_status = cli_credentials_set_machine_account(machine_account);
-       
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               r->netlogon.error_string = talloc_strdup(mem_ctx, "Could not obtain machine account password - are we joined to the domain?");
-               return nt_status;
-       }
-       
+       /* We cannot do this unless we are a BDC.  Check, before we get odd errors later */
        if (cli_credentials_get_secure_channel_type(machine_account) != SEC_CHAN_BDC) {
-               r->netlogon.error_string
+               r->out.error_string
                        = talloc_asprintf(mem_ctx, 
                                          "Our join to domain %s is not as a BDC (%d), please rejoin as a BDC",
-                                         
                                          cli_credentials_get_domain(machine_account),
                                          cli_credentials_get_secure_channel_type(machine_account));
+               talloc_free(samsync_ctx);
                return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
        }
 
-       /* Connect to DC (take a binding string for now) */
+       c = talloc(samsync_ctx, struct libnet_RpcConnect);
+       if (!c) {
+               r->out.error_string = NULL;
+               talloc_free(samsync_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       c->level              = LIBNET_RPC_CONNECT_DC_INFO;
+       if (r->in.binding_string) {
+               c->in.binding = r->in.binding_string;
+               c->in.name    = NULL;
+       } else {
+               c->in.binding = NULL;
+               c->in.name    = cli_credentials_get_domain(machine_account);
+       }
+       
+       /* prepare connect to the NETLOGON pipe of PDC */
+       c->in.dcerpc_iface      = &dcerpc_table_netlogon;
+
+       /* We must do this as the machine, not as any command-line
+        * user.  So we override the credentials in the
+        * libnet_context */
+       machine_net_ctx = talloc(samsync_ctx, struct libnet_context);
+       if (!machine_net_ctx) {
+               r->out.error_string = NULL;
+               talloc_free(samsync_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+       *machine_net_ctx = *ctx;
+       machine_net_ctx->cred = machine_account;
 
-       nt_status = dcerpc_parse_binding(mem_ctx, binding, &b);
+       /* connect to the NETLOGON pipe of the PDC */
+       nt_status = libnet_RpcConnect(machine_net_ctx, samsync_ctx, c);
        if (!NT_STATUS_IS_OK(nt_status)) {
-               r->netlogon.error_string = talloc_asprintf(mem_ctx, "Bad binding string %s\n", binding);
-               return NT_STATUS_INVALID_PARAMETER;
+               if (r->in.binding_string) {
+                       r->out.error_string = talloc_asprintf(mem_ctx,
+                                                             "Connection to NETLOGON pipe of DC %s failed: %s",
+                                                             r->in.binding_string, c->out.error_string);
+               } else {
+                       r->out.error_string = talloc_asprintf(mem_ctx,
+                                                             "Connection to NETLOGON pipe of DC for %s failed: %s",
+                                                             c->in.name, c->out.error_string);
+               }
+               talloc_free(samsync_ctx);
+               return nt_status;
        }
 
-       /* We like schannel */
-       b->flags &= ~DCERPC_AUTH_OPTIONS;
-       b->flags |= DCERPC_SCHANNEL | DCERPC_SEAL /* | DCERPC_SCHANNEL_128 */;
+       /* This makes a new pipe, on which we can do schannel.  We
+        * should do this in the RpcConnect code, but the abstaction
+        * layers do not suit yet */
 
-       /* Setup schannel */
-       nt_status = dcerpc_pipe_connect_b(mem_ctx, &p, b, 
-                                         DCERPC_NETLOGON_UUID,
-                                         DCERPC_NETLOGON_VERSION,
-                                         machine_account, ctx->event_ctx);
+       nt_status = dcerpc_secondary_connection(c->out.dcerpc_pipe, &p,
+                                               c->out.dcerpc_pipe->binding);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
+               r->out.error_string = talloc_asprintf(mem_ctx,
+                                                     "Secondary connection to NETLOGON pipe of DC %s failed: %s",
+                                                     dcerpc_server_name(p), nt_errstr(nt_status));
+               talloc_free(samsync_ctx);
                return nt_status;
        }
 
+       nt_status = dcerpc_bind_auth_schannel(samsync_ctx, p, &dcerpc_table_netlogon,
+                                             machine_account, DCERPC_AUTH_LEVEL_PRIVACY);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               r->out.error_string = talloc_asprintf(mem_ctx,
+                                                     "SCHANNEL authentication to NETLOGON pipe of DC %s failed: %s",
+                                                     dcerpc_server_name(p), nt_errstr(nt_status));
+               talloc_free(samsync_ctx);
+               return nt_status;
+       }
+
+       state = talloc(samsync_ctx, struct libnet_SamSync_state);
+       if (!state) {
+               r->out.error_string = NULL;
+               talloc_free(samsync_ctx);
+               return nt_status;
+       }               
+
+       state->domain_name     = c->out.domain_name;
+       state->domain_sid      = c->out.domain_sid;
+       state->realm           = c->out.realm;
+       state->domain_guid     = c->out.guid;
+       state->machine_net_ctx = machine_net_ctx;
+       state->netlogon_pipe   = p;
+
+       /* initialise the callback layer.  It may wish to contact the
+        * server with ldap, now we know the name */
+       
+       if (r->in.init_fn) {
+               char *error_string;
+               nt_status = r->in.init_fn(samsync_ctx, 
+                                         r->in.fn_ctx,
+                                         state, 
+                                         &error_string); 
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       r->out.error_string = talloc_steal(mem_ctx, error_string);
+                       talloc_free(samsync_ctx);
+                       return nt_status;
+               }
+       }
+
        /* get NETLOGON credentails */
 
-       nt_status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);
+       nt_status = dcerpc_schannel_creds(p->conn->security_state.generic_state, samsync_ctx, &creds);
        if (!NT_STATUS_IS_OK(nt_status)) {
-               r->netlogon.error_string = talloc_strdup(mem_ctx, "Could not obtain NETLOGON credentials from DCERPC/GENSEC layer");
+               r->out.error_string = talloc_strdup(mem_ctx, "Could not obtain NETLOGON credentials from DCERPC/GENSEC layer");
+               talloc_free(samsync_ctx);
                return nt_status;
        }
 
-       dbsync.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       /* Setup details for the synchronisation */
+       dbsync.in.logon_server = talloc_asprintf(samsync_ctx, "\\\\%s", dcerpc_server_name(p));
        dbsync.in.computername = cli_credentials_get_workstation(machine_account);
        dbsync.in.preferredmaximumlength = (uint32_t)-1;
        ZERO_STRUCT(dbsync.in.return_authenticator);
@@ -248,235 +330,69 @@ static NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *
                
                do {
                        int d;
-                       loop_ctx = talloc_named(mem_ctx, 0, "DatabaseSync loop context");
+                       loop_ctx = talloc_named(samsync_ctx, 0, "DatabaseSync loop context");
                        creds_client_authenticator(creds, &dbsync.in.credential);
                        
                        dbsync_nt_status = dcerpc_netr_DatabaseSync(p, loop_ctx, &dbsync);
                        if (!NT_STATUS_IS_OK(dbsync_nt_status) &&
                            !NT_STATUS_EQUAL(dbsync_nt_status, STATUS_MORE_ENTRIES)) {
-                               r->netlogon.error_string = talloc_asprintf(mem_ctx, "DatabaseSync failed - %s", nt_errstr(nt_status));
+                               r->out.error_string = talloc_asprintf(mem_ctx, "DatabaseSync failed - %s", nt_errstr(nt_status));
+                               talloc_free(samsync_ctx);
                                return nt_status;
                        }
                        
                        if (!creds_client_check(creds, &dbsync.out.return_authenticator.cred)) {
-                               r->netlogon.error_string = talloc_strdup(mem_ctx, "Credential chaining failed");
+                               r->out.error_string = talloc_strdup(mem_ctx, "Credential chaining on incoming DatabaseSync failed");
+                               talloc_free(samsync_ctx);
                                return NT_STATUS_ACCESS_DENIED;
                        }
                        
                        dbsync.in.sync_context = dbsync.out.sync_context;
                        
+                       /* For every single remote 'delta' entry: */
                        for (d=0; d < dbsync.out.delta_enum_array->num_deltas; d++) {
                                char *error_string = NULL;
                                delta_ctx = talloc_named(loop_ctx, 0, "DatabaseSync delta context");
+                               /* 'Fix' elements, by decrypting and
+                                * de-obfuscating the data */
                                nt_status = fix_delta(delta_ctx, 
                                                      creds, 
+                                                     r->in.rid_crypt,
                                                      dbsync.in.database_id,
                                                      &dbsync.out.delta_enum_array->delta_enum[d], 
                                                      &error_string);
                                if (!NT_STATUS_IS_OK(nt_status)) {
-                                       r->netlogon.error_string = talloc_steal(mem_ctx, error_string);
-                                       talloc_free(delta_ctx);
+                                       r->out.error_string = talloc_steal(mem_ctx, error_string);
+                                       talloc_free(samsync_ctx);
                                        return nt_status;
                                }
-                               nt_status = r->netlogon.delta_fn(delta_ctx, 
-                                                                r->netlogon.fn_ctx,
-                                                                creds,
-                                                                dbsync.in.database_id,
-                                                                &dbsync.out.delta_enum_array->delta_enum[d], 
-                                                                &error_string);
+
+                               /* Now call the callback.  This will
+                                * do something like print the data or
+                                * write to an ldb */
+                               nt_status = r->in.delta_fn(delta_ctx, 
+                                                          r->in.fn_ctx,
+                                                          dbsync.in.database_id,
+                                                          &dbsync.out.delta_enum_array->delta_enum[d], 
+                                                          &error_string);
                                if (!NT_STATUS_IS_OK(nt_status)) {
-                                       r->netlogon.error_string = talloc_steal(mem_ctx, error_string);
-                                       talloc_free(delta_ctx);
+                                       r->out.error_string = talloc_steal(mem_ctx, error_string);
+                                       talloc_free(samsync_ctx);
                                        return nt_status;
                                }
                                talloc_free(delta_ctx);
                        }
                        talloc_free(loop_ctx);
                } while (NT_STATUS_EQUAL(dbsync_nt_status, STATUS_MORE_ENTRIES));
-               nt_status = dbsync_nt_status;
-       }
-       return nt_status;
-}
-
-static NTSTATUS vampire_samdump_handle_user(TALLOC_CTX *mem_ctx,
-                                           struct creds_CredentialState *creds,
-                                           struct netr_DELTA_ENUM *delta) 
-{
-       uint32_t rid = delta->delta_id_union.rid;
-       struct netr_DELTA_USER *user = delta->delta_union.user;
-       const char *username = user->account_name.string;
-       char *hex_lm_password;
-       char *hex_nt_password;
-
-       hex_lm_password = smbpasswd_sethexpwd(mem_ctx, 
-                                             user->lm_password_present ? &user->lmpassword : NULL, 
-                                             user->acct_flags);
-       hex_nt_password = smbpasswd_sethexpwd(mem_ctx, 
-                                             user->nt_password_present ? &user->ntpassword : NULL, 
-                                             user->acct_flags);
-
-       printf("%s:%d:%s:%s:%s:LCT-%08X\n", username,
-              rid, hex_lm_password, hex_nt_password,
-              smbpasswd_encode_acb_info(mem_ctx, user->acct_flags),
-              (unsigned int)nt_time_to_unix(user->last_password_change));
-
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS vampire_samdump_handle_secret(TALLOC_CTX *mem_ctx,
-                                             struct samdump_state *samdump_state,
-                                             struct creds_CredentialState *creds,
-                                             struct netr_DELTA_ENUM *delta) 
-{
-       struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
-       const char *name = delta->delta_id_union.name;
-       struct samsync_secret *new = talloc(samdump_state, struct samsync_secret);
-
-       new->name = talloc_reference(new, name);
-       new->secret = data_blob_talloc(new, secret->current_cipher.cipher_data, secret->current_cipher.maxlen);
-       new->mtime = secret->current_cipher_set_time;
-
-       DLIST_ADD(samdump_state->secrets, new);
-
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS vampire_samdump_handle_trusted_domain(TALLOC_CTX *mem_ctx,
-                                             struct samdump_state *samdump_state,
-                                             struct creds_CredentialState *creds,
-                                             struct netr_DELTA_ENUM *delta) 
-{
-       struct netr_DELTA_TRUSTED_DOMAIN *trusted_domain = delta->delta_union.trusted_domain;
-       struct dom_sid *dom_sid = delta->delta_id_union.sid;
-
-       struct samsync_trusted_domain *new = talloc(samdump_state, struct samsync_trusted_domain);
-
-       new->name = talloc_reference(new, trusted_domain->domain_name.string);
-       new->sid = talloc_reference(new, dom_sid);
-
-       DLIST_ADD(samdump_state->trusted_domains, new);
-
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS libnet_samdump_fn(TALLOC_CTX *mem_ctx,                 
-                                 void *private,                        
-                                 struct creds_CredentialState *creds,
-                                 enum netr_SamDatabaseID database,
-                                 struct netr_DELTA_ENUM *delta,
-                                 char **error_string)
-{
-       NTSTATUS nt_status = NT_STATUS_OK;
-       struct samdump_state *samdump_state = private;
-
-       *error_string = NULL;
-       switch (delta->delta_type) {
-       case NETR_DELTA_USER:
-       {
-               /* not interested in builtin users */
-               if (database == SAM_DATABASE_DOMAIN) {
-                       nt_status = vampire_samdump_handle_user(mem_ctx, 
-                                                               creds,
-                                                               delta);
-                       break;
-               }
-       }
-       case NETR_DELTA_SECRET:
-       {
-               nt_status = vampire_samdump_handle_secret(mem_ctx,
-                                                         samdump_state,
-                                                         creds,
-                                                         delta);
-               break;
-       }
-       case NETR_DELTA_TRUSTED_DOMAIN:
-       {
-               nt_status = vampire_samdump_handle_trusted_domain(mem_ctx,
-                                                                 samdump_state,
-                                                                 creds,
-                                                                 delta);
-               break;
-       }
-       default:
-               /* Can't dump them all right now */
-               break;
-       }
-       return nt_status;
-}
-
-NTSTATUS libnet_SamDump_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamDump *r)
-{
-       NTSTATUS nt_status;
-       union libnet_SamSync r2;
-       struct samdump_state *samdump_state = talloc(mem_ctx, struct samdump_state);
-
-       struct samsync_trusted_domain *t;
-       struct samsync_secret *s;
-
-       if (!samdump_state) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       samdump_state->secrets = NULL;
-       samdump_state->trusted_domains = NULL;
-
-       r2.netlogon.level = LIBNET_SAMDUMP_NETLOGON;
-       r2.netlogon.error_string = NULL;
-       r2.netlogon.delta_fn = libnet_samdump_fn;
-       r2.netlogon.fn_ctx = samdump_state;
-       nt_status = libnet_SamSync_netlogon(ctx, mem_ctx, &r2);
-       r->generic.error_string = r2.netlogon.error_string;
-
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return nt_status;
-       }
-
-       printf("Trusted domains, sids and secrets:\n");
-       for (t=samdump_state->trusted_domains; t; t=t->next) {
-               char *secret_name = talloc_asprintf(mem_ctx, "G$$%s", t->name);
-               for (s=samdump_state->secrets; s; s=s->next) {
-                       if (StrCaseCmp(s->name, secret_name) == 0) {
-                               char *secret_string;
-                               if (convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, 
-                                                         s->secret.data, s->secret.length, 
-                                                         (void **)&secret_string) == -1) {
-                                       r->generic.error_string = talloc_asprintf(mem_ctx, 
-                                                                                 "Could not convert secret for domain %s to a string\n",
-                                                                                 t->name);
-                                       return NT_STATUS_INVALID_PARAMETER;
-                               }
-                               printf("%s\t%s\t%s\n", 
-                                      t->name, dom_sid_string(mem_ctx, t->sid), 
-                                      secret_string);
-                       }
+               
+               if (!NT_STATUS_IS_OK(dbsync_nt_status)) {
+                       r->out.error_string = talloc_asprintf(mem_ctx, "libnet_SamSync_netlogon failed: unexpected inconsistancy. Should not get error %s here", nt_errstr(nt_status));
+                       talloc_free(samsync_ctx);
+                       return dbsync_nt_status;
                }
+               nt_status = NT_STATUS_OK;
        }
+       talloc_free(samsync_ctx);
        return nt_status;
 }
 
-
-
-NTSTATUS libnet_SamDump_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamDump *r)
-{
-       NTSTATUS nt_status;
-       union libnet_SamDump r2;
-       r2.generic.level = LIBNET_SAMDUMP_NETLOGON;
-       r2.generic.error_string = NULL;
-       nt_status = libnet_SamDump(ctx, mem_ctx, &r2);
-       r->generic.error_string = r2.netlogon.error_string;
-
-       
-       return nt_status;
-}
-
-NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamDump *r)
-{
-       switch (r->generic.level) {
-       case LIBNET_SAMDUMP_GENERIC:
-               return libnet_SamDump_generic(ctx, mem_ctx, r);
-       case LIBNET_SAMDUMP_NETLOGON:
-               return libnet_SamDump_netlogon(ctx, mem_ctx, r);
-       }
-
-       return NT_STATUS_INVALID_LEVEL;
-}