Make the gpo files build for samba 4.
authorWilco Baan Hofman <wilco@baanhofman.nl>
Sun, 15 Mar 2009 03:40:12 +0000 (04:40 +0100)
committerGünther Deschner <gd@samba.org>
Mon, 20 Apr 2009 21:16:17 +0000 (23:16 +0200)
Only gpt.ini remaining. Not suitable for merge yet, samba 3 is currently broken due to some changed public API.

Signed-off-by: Günther Deschner <gd@samba.org>
libgpo/config.mk
libgpo/gpo.h
libgpo/gpo_fetch.c
libgpo/gpo_sec.c
libgpo/gpo_util.c
source4/libgpo/ads_convenience.c
source4/libgpo/ads_convenience.h
source4/libgpo/gpo.h [new file with mode: 0644]
source4/libgpo/gpo_filesync.c [new file with mode: 0644]

index 9feb2f8a6d55363d0dcc2333b66c6063838ae074..a9ad76c964a069bb8da3770df803e9c8c41f3f60 100644 (file)
@@ -3,4 +3,4 @@ PRIVATE_DEPENDENCIES = LIBLDB LIBSAMBA-NET
 
 LIBGPO_OBJ_FILES = ../libgpo/gpo_util.o ../libgpo/gpo_sec.o \
                                   ../libgpo/gpext/gpext.o ../libgpo/gpo_fetch.o \
-                       $(libgpodir)/ads_convenience.o
+                       $(libgpodir)/ads_convenience.o $(libgpodir)/gpo_filesync.o
index 35adc9425b31ca24d6dbd19332b53f3a6aa397de..a8b5ad39344c5a9c4d394b1dbde4d3b1ac733feb 100644 (file)
@@ -176,8 +176,9 @@ NTSTATUS gpo_explode_filesyspath(TALLOC_CTX *mem_ctx,
                                 char **nt_path,
                                 char **unix_path);
 NTSTATUS gpo_fetch_files(TALLOC_CTX *mem_ctx,
+                         ADS_STRUCT *ads,
+                         struct loadparm_context *lp_ctx,
                          const char *cache_path,
-                        struct cli_state *cli,
                         struct GROUP_POLICY_OBJECT *gpo);
 NTSTATUS gpo_get_sysvol_gpt_version(TALLOC_CTX *mem_ctx,
                                    const char *unix_path,
@@ -255,18 +256,20 @@ ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
 NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
                           TALLOC_CTX *mem_ctx,
                            const char *cache_path,
+                           struct loadparm_context *lp_ctx,
                           uint32_t flags,
-                          struct GROUP_POLICY_OBJECT *gpo,
-                          struct cli_state **cli_out);
+                          struct GROUP_POLICY_OBJECT *gpo);
 NTSTATUS check_refresh_gpo_list(ADS_STRUCT *ads,
                                TALLOC_CTX *mem_ctx,
                                 const char *cache_path,
+                                struct loadparm_context *lp_ctx,
                                uint32_t flags,
                                struct GROUP_POLICY_OBJECT *gpo_list);
 NTSTATUS gpo_get_unix_path(TALLOC_CTX *mem_ctx,
+                           const char *cache_path,
                           struct GROUP_POLICY_OBJECT *gpo,
                           char **unix_path);
-char *gpo_flag_str(uint32_t flags);
+char *gpo_flag_str(TALLOC_CTX *mem_ctx, uint32_t flags);
 NTSTATUS gp_find_file(TALLOC_CTX *mem_ctx,
                      uint32_t flags,
                      const char *filename,
@@ -274,6 +277,7 @@ NTSTATUS gp_find_file(TALLOC_CTX *mem_ctx,
                      const char **filename_out);
 ADS_STATUS gp_get_machine_token(ADS_STRUCT *ads,
                                TALLOC_CTX *mem_ctx,
+                               struct loadparm_context *lp_ctx,
                                const char *dn,
                                NT_USER_TOKEN **token);
 
index ee3f28d1f3ac5b9e0313e7b3e3a299c0e2a8fc4c..b6d50ad852ca9fd5e96182da0bee033cd2d6322a 100644 (file)
 #include "system/filesys.h"
 #include "../libgpo/gpo.h"
 
+#if _SAMBA_BUILD_ == 4
+#include "param/param.h"
+#include "libcli/resolve/resolve.h"
+#include "../lib/tevent/tevent.h"
+#include "libcli/libcli.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/libcli_proto.h"
+#include "libgpo/ads_convenience.h"
+#include "libgpo/gpo.h"
+#endif
+
 /****************************************************************
  explode the GPO CIFS URI into their components
 ****************************************************************/
@@ -118,24 +129,90 @@ static NTSTATUS gpo_prepare_local_store(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
+static NTSTATUS gpo_connect_server(ADS_STRUCT *ads, struct loadparm_context *lp_ctx,
+                                   const char *server, const char *service, void *ret_cli)
+{
+       NTSTATUS result;
+#if _SAMBA_BUILD_ == 3
+       struct cli_state *cli;
+
+
+       result = cli_full_connection(&cli,
+                       global_myname(),
+                       server,
+                       NULL, 0,
+                       service, "A:",
+                       ads->auth.user_name, NULL,
+                       ads->auth.password,
+                       CLI_FULL_CONNECTION_USE_KERBEROS |
+                       CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS,
+                       Undefined, NULL);
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10,("check_refresh_gpo: "
+                               "failed to connect: %s\n",
+                               nt_errstr(result)));
+                       return result;
+               }
+       }
+       *(struct cli_state **) ret_cli = cli;
+#else
+       struct smbcli_state *cli = NULL;
+       struct smbcli_options options;
+       struct smbcli_session_options session_options;
+
+       lp_smbcli_options(lp_ctx, &options);
+       lp_smbcli_session_options(lp_ctx, &session_options);
+
+       result = smbcli_full_connection(NULL, &cli,
+                       server,
+                       NULL, service,
+                       NULL /*devtype*/, NULL /* socket options */,
+                       ads->credentials,
+                       lp_resolve_context(lp_ctx),
+                       tevent_context_init(ads),
+                       &options,
+                       &session_options,
+                       lp_iconv_convenience(lp_ctx),
+                       lp_gensec_settings(ads, lp_ctx));
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10,("failed to connect: %s\n",
+                               nt_errstr(result)));
+               return result;
+       }
+       *(struct smbcli_state **) ret_cli = cli;
+#endif
+       return NT_STATUS_OK;
+}
+
 /****************************************************************
  download a full GPO via CIFS
 ****************************************************************/
 
 NTSTATUS gpo_fetch_files(TALLOC_CTX *mem_ctx,
+                         ADS_STRUCT *ads,
+                         struct loadparm_context *lp_ctx,
                          const char *cache_path,
-                        struct cli_state *cli,
                         struct GROUP_POLICY_OBJECT *gpo)
 {
        NTSTATUS result;
        char *server, *service, *nt_path, *unix_path;
        char *nt_ini_path, *unix_ini_path;
+#if _SAMBA_BUILD_ == 3
+       struct cli_state *cli;
+#else
+       struct smbcli_state *cli;
+#endif
+
 
        result = gpo_explode_filesyspath(mem_ctx, cache_path, gpo->file_sys_path,
                                         &server, &service, &nt_path,
                                         &unix_path);
        NT_STATUS_NOT_OK_RETURN(result);
 
+
+       result = gpo_connect_server(ads, lp_ctx, server, service, &cli);
+
+
        result = gpo_prepare_local_store(mem_ctx, cache_path, unix_path);
        NT_STATUS_NOT_OK_RETURN(result);
 
index 1bcfa1cbf1a3e8cb7473b01232624a6905aeba2d..5547f1e0cb9433191aed9af64567dc9276d1693d 100644 (file)
@@ -23,6 +23,7 @@
 #include "libgpo/ads_convenience.h"
 #include "librpc/gen_ndr/security.h"
 #include "librpc/gen_ndr/ndr_misc.h"
+#include "../libcli/security/secace.h"
 #include "../libgpo/gpo.h"
 #endif
 
index 720db5a2e531d41f9487eda8b0e370997ef3b99e..2dd7c496c829fecdac550c6a334a2815b500be6c 100644 (file)
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
-
+#define TALLOC_DEPRECATED 1
 #include "includes.h"
 #include "librpc/gen_ndr/ndr_misc.h"
 #if _SAMBA_BUILD_ == 4
+#include "system/filesys.h"
+#include "auth/auth.h"
 #include "../libgpo/gpo.h"
+#include "../lib/talloc/talloc.h"
 #include "source4/libgpo/ads_convenience.h"
 #endif
 #undef strdup
 
+#if 0
 #define DEFAULT_DOMAIN_POLICY "Default Domain Policy"
 #define DEFAULT_DOMAIN_CONTROLLERS_POLICY "Default Domain Controllers Policy"
+#endif
 
 /* should we store a parsed guid ? */
 struct gp_table {
@@ -571,7 +576,7 @@ ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
        }
 #endif
        if (!W_ERROR_IS_OK(werr)) {
-               gp_free_reg_ctx(reg_ctx);
+               talloc_free(reg_ctx);
                return ADS_ERROR_NT(werror_to_ntstatus(werr));
        }
 
@@ -606,7 +611,7 @@ ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
        }
 
  done:
-       gp_free_reg_ctx(reg_ctx);
+       talloc_free(reg_ctx);
        talloc_free(root_key);
        free_gp_extensions();
 
@@ -622,9 +627,9 @@ ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
 NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
                           TALLOC_CTX *mem_ctx,
                            const char *cache_path,
+                           struct loadparm_context *lp_ctx,
                           uint32_t flags,
-                          struct GROUP_POLICY_OBJECT *gpo,
-                          struct cli_state **cli_out)
+                          struct GROUP_POLICY_OBJECT *gpo)
 {
        NTSTATUS result;
        char *server = NULL;
@@ -633,7 +638,6 @@ NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
        char *unix_path = NULL;
        uint32_t sysvol_gpt_version = 0;
        char *display_name = NULL;
-       struct cli_state *cli = NULL;
 
        result = gpo_explode_filesyspath(mem_ctx, cache_path, gpo->file_sys_path,
                                         &server, &share, &nt_path, &unix_path);
@@ -663,32 +667,7 @@ NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
 
                DEBUG(1,("check_refresh_gpo: need to refresh GPO\n"));
 
-#if _SAMBA_BUILD == 3
-               if (*cli_out == NULL) {
-                       result = cli_full_connection(&cli,
-                                       global_myname(),
-                                       ads_get_ldap_server_name(ads),
-                                       /* server */
-                                       NULL, 0,
-                                       share, "A:",
-                                       ads->auth.user_name, NULL,
-                                       ads->auth.password,
-                                       CLI_FULL_CONNECTION_USE_KERBEROS |
-                                       CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS,
-                                       Undefined, NULL);
-                       if (!NT_STATUS_IS_OK(result)) {
-                               DEBUG(10,("check_refresh_gpo: "
-                                       "failed to connect: %s\n",
-                                       nt_errstr(result)));
-                               goto out;
-                       }
-                       *cli_out = cli;
-               }
-#else
-       /* TODO Implement */
-#endif
-
-               result = gpo_fetch_files(mem_ctx, cache_path, *cli_out, gpo);
+               result = gpo_fetch_files(mem_ctx, ads, lp_ctx, cache_path, gpo);
                if (!NT_STATUS_IS_OK(result)) {
                        goto out;
                }
@@ -735,11 +714,11 @@ NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
 NTSTATUS check_refresh_gpo_list(ADS_STRUCT *ads,
                                TALLOC_CTX *mem_ctx,
                                const char *cache_path,
+                                struct loadparm_context *lp_ctx,
                                uint32_t flags,
                                struct GROUP_POLICY_OBJECT *gpo_list)
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       struct cli_state *cli = NULL;
        struct GROUP_POLICY_OBJECT *gpo;
 
        if (!gpo_list) {
@@ -748,7 +727,7 @@ NTSTATUS check_refresh_gpo_list(ADS_STRUCT *ads,
 
        for (gpo = gpo_list; gpo; gpo = gpo->next) {
 
-               result = check_refresh_gpo(ads, mem_ctx, cache_path, flags, gpo, &cli);
+               result = check_refresh_gpo(ads, mem_ctx, cache_path, lp_ctx, flags, gpo);
                if (!NT_STATUS_IS_OK(result)) {
                        goto out;
                }
@@ -757,9 +736,7 @@ NTSTATUS check_refresh_gpo_list(ADS_STRUCT *ads,
        result = NT_STATUS_OK;
 
  out:
-       if (cli) {
-               cli_shutdown(cli);
-       }
+       /* FIXME close cli connection */
 
        return result;
 }
@@ -768,45 +745,46 @@ NTSTATUS check_refresh_gpo_list(ADS_STRUCT *ads,
 ****************************************************************/
 
 NTSTATUS gpo_get_unix_path(TALLOC_CTX *mem_ctx,
+                           const char *cache_path,
                           struct GROUP_POLICY_OBJECT *gpo,
                           char **unix_path)
 {
        char *server, *share, *nt_path;
-       return gpo_explode_filesyspath(mem_ctx, gpo->file_sys_path,
+       return gpo_explode_filesyspath(mem_ctx, cache_path, gpo->file_sys_path,
                                       &server, &share, &nt_path, unix_path);
 }
 
 /****************************************************************
 ****************************************************************/
 
-char *gpo_flag_str(uint32_t flags)
+char *gpo_flag_str(TALLOC_CTX *ctx, uint32_t flags)
 {
-       fstring str = "";
+       char *str = NULL;
 
        if (flags == 0) {
                return NULL;
        }
 
        if (flags & GPO_INFO_FLAG_SLOWLINK)
-               fstrcat(str, "GPO_INFO_FLAG_SLOWLINK ");
+               str = talloc_append_string(ctx, str, "GPO_INFO_FLAG_SLOWLINK ");
        if (flags & GPO_INFO_FLAG_VERBOSE)
-               fstrcat(str, "GPO_INFO_FLAG_VERBOSE ");
+               str = talloc_append_string(ctx, str, "GPO_INFO_FLAG_VERBOSE ");
        if (flags & GPO_INFO_FLAG_SAFEMODE_BOOT)
-               fstrcat(str, "GPO_INFO_FLAG_SAFEMODE_BOOT ");
+               str = talloc_append_string(ctx, str, "GPO_INFO_FLAG_SAFEMODE_BOOT ");
        if (flags & GPO_INFO_FLAG_NOCHANGES)
-               fstrcat(str, "GPO_INFO_FLAG_NOCHANGES ");
+               str = talloc_append_string(ctx, str, "GPO_INFO_FLAG_NOCHANGES ");
        if (flags & GPO_INFO_FLAG_MACHINE)
-               fstrcat(str, "GPO_INFO_FLAG_MACHINE ");
+               str = talloc_append_string(ctx, str, "GPO_INFO_FLAG_MACHINE ");
        if (flags & GPO_INFO_FLAG_LOGRSOP_TRANSITION)
-               fstrcat(str, "GPO_INFO_FLAG_LOGRSOP_TRANSITION ");
+               str = talloc_append_string(ctx, str, "GPO_INFO_FLAG_LOGRSOP_TRANSITION ");
        if (flags & GPO_INFO_FLAG_LINKTRANSITION)
-               fstrcat(str, "GPO_INFO_FLAG_LINKTRANSITION ");
+               str = talloc_append_string(ctx, str, "GPO_INFO_FLAG_LINKTRANSITION ");
        if (flags & GPO_INFO_FLAG_FORCED_REFRESH)
-               fstrcat(str, "GPO_INFO_FLAG_FORCED_REFRESH ");
+               str = talloc_append_string(ctx, str, "GPO_INFO_FLAG_FORCED_REFRESH ");
        if (flags & GPO_INFO_FLAG_BACKGROUND)
-               fstrcat(str, "GPO_INFO_FLAG_BACKGROUND ");
+               str = talloc_append_string(ctx, str, "GPO_INFO_FLAG_BACKGROUND ");
 
-       return strdup(str);
+       return str;
 }
 
 /****************************************************************
@@ -857,12 +835,17 @@ NTSTATUS gp_find_file(TALLOC_CTX *mem_ctx,
 
 ADS_STATUS gp_get_machine_token(ADS_STRUCT *ads,
                                TALLOC_CTX *mem_ctx,
+                               struct loadparm_context *lp_ctx,
                                const char *dn,
                                NT_USER_TOKEN **token)
 {
        NT_USER_TOKEN *ad_token = NULL;
        ADS_STATUS status;
+#if _SAMBA_BUILD_ == 4
+       struct auth_session_info *info;
+#else
        NTSTATUS ntstatus;
+#endif
 
 #ifndef HAVE_ADS
        return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
@@ -871,12 +854,15 @@ ADS_STATUS gp_get_machine_token(ADS_STRUCT *ads,
        if (!ADS_ERR_OK(status)) {
                return status;
        }
-
+#if _SAMBA_BUILD_ == 4
+       info = system_session(mem_ctx, lp_ctx);
+       *token = info->security_token;
+#else
        ntstatus = merge_nt_token(mem_ctx, ad_token, get_system_token(),
                                  token);
        if (!NT_STATUS_IS_OK(ntstatus)) {
                return ADS_ERROR_NT(ntstatus);
        }
-
+#endif
        return ADS_SUCCESS;
 }
index 77c4f5bdc2bd78c3332a252e80d11e1fb85ebad1..6e2dbca5381b77eef47798de3041b3cfce175ed1 100644 (file)
@@ -258,6 +258,9 @@ bool nt_token_check_sid( const struct dom_sid *sid, const NT_USER_TOKEN *token)
 
        return false;
 }
+const char *ads_get_ldap_server_name(ADS_STRUCT *ads) {
+       return ads->ldap_server_name;
+}
 
 
 /*
index bce2cc4eeafbaae00958d0e09739df54cd670e83..ce2b9b6a06ba17a8d8495ebb59aebae1b13391ac 100644 (file)
 typedef struct {
        struct libnet_context *netctx;
        struct ldb_context *ldbctx;
+       char *ldap_server_name;
+
+       /* State information for the smb connection */
+       struct cli_credentials *credentials;
+       struct smbcli_state *cli;
 } ADS_STRUCT;
 
 
@@ -92,6 +97,7 @@ bool nt_token_check_sid( const struct dom_sid *sid, const NT_USER_TOKEN *token);
 ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx);
 ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods, const char *name, const char *val);
 ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods);
+const char *ads_get_ldap_server_name(ADS_STRUCT *ads);
 
 
 #endif
diff --git a/source4/libgpo/gpo.h b/source4/libgpo/gpo.h
new file mode 100644 (file)
index 0000000..3e5cb06
--- /dev/null
@@ -0,0 +1,36 @@
+
+/*
+   Samba CIFS implementation
+   ADS convenience functions for GPO
+
+   Copyright (C) 2008 Jelmer Vernooij, jelmer@samba.org
+   Copyright (C) 2008 Wilco Baan Hofman, wilco@baanhofman.nl
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __LIBGPO_GPO_H__
+#define __LIBGPO_GPO_H__
+
+NTSTATUS gpo_copy_file(TALLOC_CTX *mem_ctx,
+                      struct smbcli_state *cli,
+                      const char *nt_path,
+                      const char *unix_path);
+
+NTSTATUS gpo_sync_directories(TALLOC_CTX *mem_ctx,
+                             struct smbcli_state *cli,
+                             const char *nt_path,
+                             const char *local_path);
+
+#endif
diff --git a/source4/libgpo/gpo_filesync.c b/source4/libgpo/gpo_filesync.c
new file mode 100644 (file)
index 0000000..3f6f5f7
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Group Policy Object Support
+ *
+ *  Copyright (C) Guenther Deschner 2006
+ *  Copyright (C) Wilco Baan Hofman 2008
+ *
+ *  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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "libcli/libcli.h"
+#include "system/filesys.h"
+
+
+struct sync_context {
+       TALLOC_CTX *mem_ctx;
+       struct smbcli_state *cli;
+       char *remote_path;
+       char *local_path;
+       char *mask;
+       uint16_t attribute;
+};
+
+static void gpo_sync_func(struct clilist_file_info *info,
+                         const char *mask,
+                         void *state);
+
+NTSTATUS gpo_copy_file(TALLOC_CTX *mem_ctx,
+                      struct smbcli_state *cli,
+                      const char *nt_path,
+                      const char *unix_path)
+{
+       NTSTATUS result;
+       int fnum;
+       int fd = 0;
+       char *data = NULL;
+       static int io_bufsize = 64512;
+       int read_size = io_bufsize;
+       off_t nread = 0;
+
+       if ((fnum = smbcli_open(cli->tree, nt_path, O_RDONLY, DENY_NONE)) == -1) {
+               result = NT_STATUS_NO_SUCH_FILE;
+               goto out;
+       }
+
+       if ((fd = open(unix_path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
+               result = map_nt_error_from_unix(errno);
+               goto out;
+       }
+
+       if ((data = talloc_size(mem_ctx, read_size)) == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
+
+       while (1) {
+
+               int n = smbcli_read(cli->tree, fnum, data, nread, read_size);
+
+               if (n <= 0)
+                       break;
+
+               if (write(fd, data, n) != n) {
+                       break;
+               }
+
+               nread += n;
+       }
+
+       result = NT_STATUS_OK;
+
+ out:
+       SAFE_FREE(data);
+       if (fnum) {
+               smbcli_close(cli->tree, fnum);
+       }
+       if (fd) {
+               close(fd);
+       }
+
+       return result;
+}
+
+/****************************************************************
+ copy dir
+****************************************************************/
+
+static NTSTATUS gpo_copy_dir(const char *nt_dir, const char *unix_path)
+{
+       if ((mkdir(unix_path, 0644)) < 0 && errno != EEXIST) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/****************************************************************
+ sync files
+****************************************************************/
+
+static bool gpo_sync_files(struct sync_context *ctx)
+{
+       DEBUG(3,("calling cli_list with mask: %s\n", ctx->mask));
+
+       if (smbcli_list(ctx->cli->tree,
+                    ctx->mask,
+                    ctx->attribute,
+                    gpo_sync_func,
+                    ctx) == -1) {
+               DEBUG(1,("listing [%s] failed with error: %s\n",
+                       ctx->mask, smbcli_errstr(ctx->cli->tree)));
+               return false;
+       }
+
+       return true;
+}
+
+/****************************************************************
+ syncronisation call back
+****************************************************************/
+
+static void gpo_sync_func(struct clilist_file_info *info,
+                         const char *mask,
+                         void *state)
+{
+       NTSTATUS result;
+       struct sync_context *ctx;
+       char *nt_filename, *unix_filename;
+       char *nt_dir, *unix_dir;
+       char *old_nt_dir, *old_unix_dir;
+
+       ctx = (struct sync_context *)state;
+
+       if (strequal(info->name, ".") || strequal(info->name, "..")) {
+               return;
+       }
+
+       DEBUG(5,("gpo_sync_func: got mask: [%s], name: [%s]\n",
+               mask, info->name));
+
+       if (info->attrib & FILE_ATTRIBUTE_DIRECTORY) {
+
+               DEBUG(3,("got dir: [%s]\n", info->name));
+
+               nt_dir = talloc_asprintf(ctx->mem_ctx, "%s\\%s",
+                               ctx->remote_path,
+                               info->name);
+
+               unix_dir = talloc_asprintf(ctx->mem_ctx, "%s/%s",
+                               ctx->local_path,
+                               info->name);
+
+               result = gpo_copy_dir(nt_dir, unix_dir);
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(1,("failed to copy dir: %s\n",
+                               nt_errstr(result)));
+               }
+
+               old_nt_dir = ctx->remote_path;
+               ctx->remote_path = talloc_strdup(ctx->mem_ctx, nt_dir);
+
+               old_unix_dir = ctx->local_path;
+               ctx->local_path = talloc_strdup(ctx->mem_ctx, unix_dir);
+
+               ctx->mask = talloc_asprintf(ctx->mem_ctx,
+                                       "%s\\*",
+                                       nt_dir);
+               if (!ctx->local_path || !ctx->mask || !ctx->remote_path) {
+                       DEBUG(0,("gpo_sync_func: ENOMEM\n"));
+                       return;
+               }
+               if (!gpo_sync_files(ctx)) {
+                       DEBUG(0,("could not sync files\n"));
+               }
+
+               ctx->remote_path = old_nt_dir;
+               ctx->local_path = old_unix_dir;
+               return;
+       }
+
+       DEBUG(3,("got file: [%s]\n", info->name));
+
+       nt_filename = talloc_asprintf(ctx->mem_ctx, "%s\\%s",
+                       ctx->remote_path,
+                       info->name);
+
+       unix_filename = talloc_asprintf(ctx->mem_ctx, "%s/%s",
+                       ctx->local_path,
+                       info->name);
+
+       result = gpo_copy_file(ctx->mem_ctx, ctx->cli,
+                              nt_filename, unix_filename);
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(1,("failed to copy file: %s\n",
+                       nt_errstr(result)));
+       }
+}
+
+
+/****************************************************************
+ list a remote directory and download recursivly
+****************************************************************/
+
+NTSTATUS gpo_sync_directories(TALLOC_CTX *mem_ctx,
+                             struct smbcli_state *cli,
+                             const char *nt_path,
+                             const char *local_path)
+{
+       struct sync_context ctx;
+
+       ctx.mem_ctx     = mem_ctx;
+       ctx.cli         = cli;
+       ctx.remote_path = discard_const_p(char, nt_path);
+       ctx.local_path  = discard_const_p(char, local_path);
+       ctx.attribute   = (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
+
+       ctx.mask = talloc_asprintf(mem_ctx,
+                               "%s\\*",
+                               nt_path);
+       if (!ctx.mask) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!gpo_sync_files(&ctx)) {
+               return NT_STATUS_NO_SUCH_FILE;
+       }
+
+       return NT_STATUS_OK;
+}