r25554: Convert last instances of BOOL, True and False to the standard types.
[jra/samba/.git] / source4 / libnet / libnet_vampire.c
index 26e39392051f1b3f2e10fb272f83926f082db300..dff915df71d865fa0c1f8c4dca8b7b0e7ec71399 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_netlogon_c.h"
+#include "param/param.h"
 
 
 /**
@@ -32,6 +38,7 @@
  */
 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) 
@@ -44,14 +51,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) {
@@ -66,17 +75,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;
-                               user->lm_password_present = True;
+                               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;
-                               user->nt_password_present = True;
+                               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;
                }
@@ -112,6 +130,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)
@@ -123,6 +142,7 @@ static NTSTATUS fix_delta(TALLOC_CTX *mem_ctx,
        {
                nt_status = fix_user(mem_ctx, 
                                     creds,
+                                    rid_crypt,
                                     database,
                                     delta,
                                     error_string);
@@ -153,6 +173,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
        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;
 
@@ -164,7 +185,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
                        talloc_free(samsync_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
-               cli_credentials_set_conf(machine_account);
+               cli_credentials_set_conf(machine_account, global_loadparm);
                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?");
@@ -180,7 +201,6 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
                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);
@@ -194,15 +214,17 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
                return NT_STATUS_NO_MEMORY;
        }
 
+       c->level              = LIBNET_RPC_CONNECT_DC_INFO;
        if (r->in.binding_string) {
-               c->level      = LIBNET_RPC_CONNECT_BINDING;
                c->in.binding = r->in.binding_string;
+               c->in.name    = NULL;
        } else {
-               /* prepare connect to the NETLOGON pipe of PDC */
-               c->level      = LIBNET_RPC_CONNECT_PDC;
+               c->in.binding = NULL;
                c->in.name    = cli_credentials_get_domain(machine_account);
        }
-       c->in.dcerpc_iface      = &dcerpc_table_netlogon;
+       
+       /* prepare connect to the NETLOGON pipe of PDC */
+       c->in.dcerpc_iface      = &ndr_table_netlogon;
 
        /* We must do this as the machine, not as any command-line
         * user.  So we override the credentials in the
@@ -217,11 +239,17 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
        machine_net_ctx->cred = machine_account;
 
        /* connect to the NETLOGON pipe of the PDC */
-       nt_status = libnet_RpcConnect(machine_net_ctx, c, c);
+       nt_status = libnet_RpcConnect(machine_net_ctx, samsync_ctx, c);
        if (!NT_STATUS_IS_OK(nt_status)) {
-               r->out.error_string = talloc_asprintf(mem_ctx,
-                                                     "Connection to NETLOGON pipe of DC failed: %s",
-                                                     c->out.error_string);
+               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;
        }
@@ -241,7 +269,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
                return nt_status;
        }
 
-       nt_status = dcerpc_bind_auth_schannel(samsync_ctx, p, &dcerpc_table_netlogon,
+       nt_status = dcerpc_bind_auth_schannel(samsync_ctx, p, &ndr_table_netlogon,
                                              machine_account, DCERPC_AUTH_LEVEL_PRIVACY);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -252,6 +280,36 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_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, samsync_ctx, &creds);
@@ -261,7 +319,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
                return nt_status;
        }
 
-       /* Setup details for the syncronisation */
+       /* 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;
@@ -279,13 +337,13 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
                        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->out.error_string = talloc_asprintf(samsync_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->out.error_string = talloc_strdup(samsync_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;
                        }
@@ -297,14 +355,15 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
                                char *error_string = NULL;
                                delta_ctx = talloc_named(loop_ctx, 0, "DatabaseSync delta context");
                                /* 'Fix' elements, by decrypting and
-                                * de-obfustiating the data */
+                                * 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->out.error_string = talloc_steal(samsync_ctx, error_string);
+                                       r->out.error_string = talloc_steal(mem_ctx, error_string);
                                        talloc_free(samsync_ctx);
                                        return nt_status;
                                }
@@ -314,12 +373,11 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
                                 * write to an ldb */
                                nt_status = r->in.delta_fn(delta_ctx, 
                                                           r->in.fn_ctx,
-                                                          creds,
                                                           dbsync.in.database_id,
                                                           &dbsync.out.delta_enum_array->delta_enum[d], 
                                                           &error_string);
                                if (!NT_STATUS_IS_OK(nt_status)) {
-                                       r->out.error_string = talloc_steal(samsync_ctx, error_string);
+                                       r->out.error_string = talloc_steal(mem_ctx, error_string);
                                        talloc_free(samsync_ctx);
                                        return nt_status;
                                }
@@ -327,7 +385,13 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
                        }
                        talloc_free(loop_ctx);
                } while (NT_STATUS_EQUAL(dbsync_nt_status, STATUS_MORE_ENTRIES));
-               nt_status = dbsync_nt_status;
+               
+               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;