Add gpo create functionality. Also fix gPLink handling bugs
authorWilco Baan Hofman <wilco@baanhofman.nl>
Thu, 6 May 2010 16:42:14 +0000 (18:42 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Sun, 20 Jun 2010 15:19:11 +0000 (17:19 +0200)
Signed-off-by: Jelmer Vernooij <jelmer@samba.org>
source4/lib/policy/config.mk
source4/lib/policy/gp_filesys.c
source4/lib/policy/gp_ldap.c
source4/lib/policy/gp_manage.c [new file with mode: 0644]
source4/lib/policy/policy.h
source4/lib/policy/wscript_build
source4/utils/net/net_gpo.c

index 74403f8565a64726092979d1cd25209a975982d7..0a3e731c542662e302f58d4b81a5df722a0af86a 100644 (file)
@@ -1,6 +1,6 @@
 [SUBSYSTEM::policy]
 PRIVATE_DEPENDENCIES = LIBLDB LIBSAMBA-NET
 
-policy_OBJ_FILES = $(policydir)/gp_ldap.o $(policydir)/gp_filesys.c
+policy_OBJ_FILES = $(policydir)/gp_ldap.o $(policydir)/gp_filesys.c $(policydir)/gp_manage.c
 
 PC_FILES += $(policydir)/policy.pc
index 771ba5e072b065ec5cef83720d47210594eb2556..388c1d25b8d45c5ef8a23b8b0e31c5684ec3b62e 100644 (file)
@@ -24,6 +24,8 @@
 #include "libcli/resolve/resolve.h"
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
 
 #define GP_MAX_DEPTH 25
 
@@ -184,7 +186,7 @@ static NTSTATUS gp_cli_connect(struct gp_context *gp_ctx)
        return NT_STATUS_OK;
 }
 
-NTSTATUS gp_fetch_gpo (struct gp_context *gp_ctx, struct gp_object *gpo, const char **ret_local_path)
+NTSTATUS gp_fetch_gpt (struct gp_context *gp_ctx, struct gp_object *gpo, const char **ret_local_path)
 {
        TALLOC_CTX *mem_ctx;
        struct gp_list_state *state;
@@ -246,3 +248,160 @@ NTSTATUS gp_fetch_gpo (struct gp_context *gp_ctx, struct gp_object *gpo, const c
        talloc_free(mem_ctx);
        return NT_STATUS_OK;
 }
+
+static NTSTATUS push_recursive (struct gp_context *gp_ctx, const char *local_path, const char *remote_path, int depth)
+{
+       DIR *dir;
+       struct dirent *dirent;
+       char *entry_local_path;
+       char *entry_remote_path;
+       int local_fd, remote_fd;
+       int buf[1024];
+       int nread, total_read;
+
+       dir = opendir(local_path);
+       while ((dirent = readdir(dir)) != NULL) {
+               if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) {
+                       continue;
+               }
+
+               entry_local_path = talloc_asprintf(gp_ctx, "%s/%s", local_path, dirent->d_name);
+               entry_remote_path = talloc_asprintf(gp_ctx, "%s\\%s", remote_path, dirent->d_name);
+               if (dirent->d_type == DT_DIR) {
+                       DEBUG(6, ("Pushing directory %s to %s on sysvol\n", entry_local_path, entry_remote_path));
+                       smbcli_mkdir(gp_ctx->cli->tree, entry_remote_path);
+                       if (depth < GP_MAX_DEPTH)
+                               push_recursive(gp_ctx, entry_local_path, entry_remote_path, depth+1);
+               } else {
+                       DEBUG(6, ("Pushing file %s to %s on sysvol\n", entry_local_path, entry_remote_path));
+                       remote_fd = smbcli_open(gp_ctx->cli->tree, entry_remote_path, O_WRONLY | O_CREAT, 0);
+                       if (remote_fd < 0) {
+                               talloc_free(entry_local_path);
+                               talloc_free(entry_remote_path);
+                               DEBUG(0, ("Failed to create remote file: %s\n", entry_remote_path));
+                               return NT_STATUS_UNSUCCESSFUL;
+                       }
+                       local_fd = open(entry_local_path, O_RDONLY);
+                       if (local_fd < 0) {
+                               talloc_free(entry_local_path);
+                               talloc_free(entry_remote_path);
+                               DEBUG(0, ("Failed to open local file: %s\n", entry_local_path));
+                               return NT_STATUS_UNSUCCESSFUL;
+                       }
+                       total_read = 0;
+                       while ((nread = read(local_fd, &buf, sizeof(buf)))) {
+                               smbcli_write(gp_ctx->cli->tree, remote_fd, 0, &buf, total_read, nread);
+                               total_read += nread;
+                       }
+
+                       close(local_fd);
+                       smbcli_close(gp_ctx->cli->tree, remote_fd);
+               }
+               talloc_free(entry_local_path);
+               talloc_free(entry_remote_path);
+       }
+       closedir(dir);
+
+       return NT_STATUS_OK;
+}
+
+
+
+NTSTATUS gp_push_gpt(struct gp_context *gp_ctx, const char *local_path, const char *file_sys_path)
+{
+       NTSTATUS status;
+       unsigned int i, bkslash_cnt;
+       char *share_path;
+
+       if (gp_ctx->cli == NULL) {
+               status = gp_cli_connect(gp_ctx);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("Failed to create cli connection to DC\n"));
+                       return status;
+               }
+       }
+
+       /* Get the path from the share down (\\..\..\(this\stuff) */
+       for (i = 0, bkslash_cnt = 0; file_sys_path[i] != '\0'; i++) {
+               if (file_sys_path[i] == '\\')
+                       bkslash_cnt++;
+
+               if (bkslash_cnt == 4) {
+                       share_path = talloc_strdup(gp_ctx, &file_sys_path[i]);
+                       break;
+               }
+       }
+
+       DEBUG(5, ("Copying %s to %s on sysvol\n", local_path, share_path));
+
+       smbcli_mkdir(gp_ctx->cli->tree, share_path);
+
+       status = push_recursive(gp_ctx, local_path, share_path, 0);
+
+       talloc_free(share_path);
+       return status;
+}
+
+NTSTATUS gp_create_gpt(struct gp_context *gp_ctx, const char *name, const char *file_sys_path)
+{
+       TALLOC_CTX *mem_ctx;
+       const char *tmp_dir, *policy_dir, *tmp_str;
+       int rv;
+       int fd;
+       NTSTATUS status;
+
+       /* Create a forked memory context, as a base for everything here */
+       mem_ctx = talloc_new(gp_ctx);
+
+       tmp_dir = gp_tmpdir(mem_ctx);
+       policy_dir = talloc_asprintf(mem_ctx, "%s/%s", tmp_dir, name);
+       rv = mkdir(policy_dir, 0755);
+       if (rv < 0) {
+               DEBUG(0, ("Could not create the policy dir: %s\n", policy_dir));
+               talloc_free(mem_ctx);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       tmp_str = talloc_asprintf(mem_ctx, "%s/User", policy_dir);
+       rv = mkdir(tmp_str, 0755);
+       if (rv < 0) {
+               DEBUG(0, ("Could not create the User dir: %s\n", tmp_str));
+               talloc_free(mem_ctx);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       tmp_str = talloc_asprintf(mem_ctx, "%s/Machine", policy_dir);
+       rv = mkdir(tmp_str, 0755);
+       if (rv < 0) {
+               DEBUG(0, ("Could not create the Machine dir: %s\n", tmp_str));
+               talloc_free(mem_ctx);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       tmp_str = talloc_asprintf(mem_ctx, "%s/GPT.INI", policy_dir);
+       fd = open(tmp_str, O_CREAT | O_WRONLY, 0644);
+       if (fd < 0) {
+               DEBUG(0, ("Could not create the GPT.INI: %s\n", tmp_str));
+               talloc_free(mem_ctx);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       rv = write(fd, "[General]\r\nVersion=0\r\n", 23);
+       if (rv != 23) {
+               DEBUG(0, ("Short write in GPT.INI\n"));
+               talloc_free(mem_ctx);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       close(fd);
+
+
+       status = gp_push_gpt(gp_ctx, policy_dir, file_sys_path);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(mem_ctx);
+               return status;
+       }
+
+       talloc_free(mem_ctx);
+       return NT_STATUS_OK;
+}
index a7d5eb6158f03185c7ec63e880c49018ada133fe..b8b24d4c8609037f56b91ee4b590e316c0bc615b 100644 (file)
@@ -367,8 +367,7 @@ NTSTATUS gp_get_gplinks(struct gp_context *gp_ctx, const char *dn_str, struct gp
                        }
                }
        }
-       DEBUG(0, ("Object or gPLink attribute not found.\n"));
-       return NT_STATUS_NOT_FOUND;
+       gplink_str = talloc_strdup(mem_ctx, "");
 
        found:
 
@@ -661,14 +660,22 @@ NTSTATUS gp_del_gplink(struct gp_context *gp_ctx, const char *dn_str, const char
        msg = ldb_msg_new(mem_ctx);
        msg->dn = dn;
 
-       rv = ldb_msg_add_string(msg, "gPLink", gplink_str);
-       if (rv != 0) {
-               DEBUG(0, ("LDB message add string failed: %s\n", ldb_strerror(rv)));
-               talloc_free(mem_ctx);
-               return NT_STATUS_UNSUCCESSFUL;
+       if (strcmp(gplink_str, "") == 0) {
+               rv = ldb_msg_add_empty(msg, "gPLink", LDB_FLAG_MOD_DELETE, NULL);
+               if (rv != 0) {
+                       DEBUG(0, ("LDB message add empty element failed: %s\n", ldb_strerror(rv)));
+                       talloc_free(mem_ctx);
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       } else {
+               rv = ldb_msg_add_string(msg, "gPLink", gplink_str);
+               if (rv != 0) {
+                       DEBUG(0, ("LDB message add string failed: %s\n", ldb_strerror(rv)));
+                       talloc_free(mem_ctx);
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+               msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
        }
-       msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
-
        rv = ldb_modify(gp_ctx->ldb_ctx, msg);
        if (rv != 0) {
                DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
@@ -740,3 +747,118 @@ NTSTATUS gp_set_inheritance(struct gp_context *gp_ctx, const char *dn_str, enum
        talloc_free(msg);
        return NT_STATUS_OK;
 }
+
+NTSTATUS gp_create_ldap_gpo(struct gp_context *gp_ctx, struct gp_object *gpo)
+{
+       struct ldb_message *msg;
+       TALLOC_CTX *mem_ctx;
+       int rv;
+       char *dn_str;
+       struct ldb_dn *child_dn, *gpo_dn;
+
+       mem_ctx = talloc_new(gp_ctx);
+
+       /* CN={GUID} */
+       msg = ldb_msg_new(mem_ctx);
+
+       msg->dn = ldb_get_default_basedn(gp_ctx->ldb_ctx);
+       dn_str = talloc_asprintf(mem_ctx, "CN=%s,CN=Policies,CN=System", gpo->name);
+       child_dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
+       rv = ldb_dn_add_child(msg->dn, child_dn);
+       if (!rv) goto ldb_msg_add_error;
+
+       rv = ldb_msg_add_string(msg, "objectClass", "top");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "objectClass", "container");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "objectClass", "groupPolicyContainer");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "displayName", gpo->display_name);
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "name", gpo->name);
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "CN", gpo->name);
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "gPCFileSysPath", gpo->file_sys_path);
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "flags",
+                       talloc_asprintf(mem_ctx, "%d", gpo->flags));
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "versionNumber",
+                       talloc_asprintf(mem_ctx, "%d", gpo->version));
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "gpCFunctionalityVersion", "2");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+
+       /* FIXME Add security descriptor as well */
+
+       rv = ldb_add(gp_ctx->ldb_ctx, msg);
+       if (rv != LDB_SUCCESS) {
+               DEBUG(0, ("LDB add error: %s\n", ldb_errstring(gp_ctx->ldb_ctx)));
+               talloc_free(mem_ctx);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       gpo_dn = msg->dn;
+
+       /* CN=User */
+       msg = ldb_msg_new(mem_ctx);
+       msg->dn = ldb_dn_copy(mem_ctx, gpo_dn);
+       child_dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, "CN=User");
+       rv = ldb_dn_add_child(msg->dn, child_dn);
+       if (!rv) goto ldb_msg_add_error;
+
+       rv = ldb_msg_add_string(msg, "objectClass", "top");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "objectClass", "container");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "CN", "User");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "name", "User");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+
+       rv = ldb_add(gp_ctx->ldb_ctx, msg);
+       if (rv != LDB_SUCCESS) {
+               DEBUG(0, ("LDB add error: %s\n", ldb_errstring(gp_ctx->ldb_ctx)));
+               talloc_free(mem_ctx);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       /* CN=Machine */
+       msg = ldb_msg_new(mem_ctx);
+       msg->dn = ldb_dn_copy(mem_ctx, gpo_dn);
+       child_dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, "CN=Machine");
+       rv = ldb_dn_add_child(msg->dn, child_dn);
+       if (!rv) goto ldb_msg_add_error;
+
+       rv = ldb_msg_add_string(msg, "objectClass", "top");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "objectClass", "container");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "CN", "Machine");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+       rv = ldb_msg_add_string(msg, "name", "Machine");
+       if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
+
+       rv = ldb_add(gp_ctx->ldb_ctx, msg);
+       if (rv != LDB_SUCCESS) {
+               DEBUG(0, ("LDB add error: %s\n", ldb_errstring(gp_ctx->ldb_ctx)));
+               talloc_free(mem_ctx);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+
+       talloc_free(mem_ctx);
+       return NT_STATUS_OK;
+
+       ldb_msg_add_error:
+       DEBUG(0, ("LDB Error adding element to ldb message\n"));
+       talloc_free(mem_ctx);
+       return NT_STATUS_UNSUCCESSFUL;
+}
diff --git a/source4/lib/policy/gp_manage.c b/source4/lib/policy/gp_manage.c
new file mode 100644 (file)
index 0000000..d273678
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Group Policy Object Support
+ *  Copyright (C) Wilco Baan Hofman 2010
+ *
+ *  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/security/dom_sid.h"
+#include "../libcli/security/security_descriptor.h"
+#include "../librpc/ndr/libndr.h"
+#include "param/param.h"
+#include "lib/policy/policy.h"
+
+static uint32_t gp_ads_to_dir_access_mask(uint32_t access_mask)
+{
+       uint32_t fs_mask;
+
+       /* Copy the standard access mask */
+       fs_mask = access_mask & 0x001F0000;
+
+       /* When READ_PROP and LIST_CONTENTS are set, read access is granted on the GPT */
+       if (access_mask & SEC_ADS_READ_PROP && access_mask & SEC_ADS_LIST) {
+               fs_mask |= SEC_STD_SYNCHRONIZE | SEC_DIR_LIST | SEC_DIR_READ_ATTRIBUTE |
+                               SEC_DIR_READ_EA | SEC_DIR_TRAVERSE;
+       }
+
+       /* When WRITE_PROP is set, full write access is granted on the GPT */
+       if (access_mask & SEC_ADS_WRITE_PROP) {
+               fs_mask |= SEC_STD_SYNCHRONIZE | SEC_DIR_WRITE_ATTRIBUTE |
+                               SEC_DIR_WRITE_EA | SEC_DIR_ADD_FILE |
+                               SEC_DIR_ADD_SUBDIR;
+       }
+
+       /* Map CREATE_CHILD to add file and add subdir */
+       if (access_mask & SEC_ADS_CREATE_CHILD)
+               fs_mask |= SEC_DIR_ADD_FILE | SEC_DIR_ADD_SUBDIR;
+
+       /* Map ADS delete child to dir delete child */
+       if (access_mask & SEC_ADS_DELETE_CHILD)
+               fs_mask |= SEC_DIR_DELETE_CHILD;
+
+       return fs_mask;
+}
+
+NTSTATUS gp_create_gpt_security_descriptor (TALLOC_CTX *mem_ctx, struct security_descriptor *ds_sd, struct security_descriptor **ret)
+{
+       struct security_descriptor *fs_sd;
+       uint32_t i;
+
+       /* Allocate the file system security descriptor */
+       fs_sd = talloc(mem_ctx, struct security_descriptor);
+
+       /* Copy the basic information from the directory server security descriptor */
+       fs_sd->owner_sid = talloc_memdup(fs_sd, fs_sd->owner_sid, sizeof(struct dom_sid));
+       fs_sd->group_sid = talloc_memdup(fs_sd, fs_sd->group_sid, sizeof(struct dom_sid));
+       fs_sd->type = ds_sd->type;
+       fs_sd->revision = ds_sd->revision;
+
+       /* Copy the sacl */
+       fs_sd->sacl = security_acl_dup(fs_sd, ds_sd->sacl);
+
+       /* Copy the dacl */
+       fs_sd->dacl = talloc_zero(fs_sd, struct security_acl);
+
+       for (i = 0; i < ds_sd->dacl->num_aces; i++) {
+               char *trustee = dom_sid_string(fs_sd, &ds_sd->dacl->aces[i].trustee);
+               struct security_ace *ace;
+
+               /* Don't add the allow for SID_BUILTIN_PREW2K */
+               if (!(ds_sd->dacl->aces[i].type & SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) &&
+                               strcmp(trustee, SID_BUILTIN_PREW2K) == 0) {
+                       talloc_free(trustee);
+                       continue;
+               }
+
+               /* Copy the ace from the directory server security descriptor */
+               ace = talloc_memdup(fs_sd, &ds_sd->dacl->aces[i], sizeof(struct security_ace));
+
+               /* Set specific inheritance flags for within the GPO */
+               ace->flags |= SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_CONTAINER_INHERIT;
+               if (strcmp(trustee, SID_CREATOR_OWNER) == 0) {
+                       ace->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
+               }
+
+               /* Get a directory access mask from the assigned access mask on the LDAP object */
+               ace->access_mask = gp_ads_to_dir_access_mask(ace->access_mask);
+
+               /* Add the ace to the security descriptor DACL */
+               security_descriptor_dacl_add(fs_sd, ace);
+
+               /* Clean up the allocated data in this iteration */
+               talloc_free(trustee);
+       }
+
+       *ret = fs_sd;
+       return NT_STATUS_OK;
+}
+
+
+NTSTATUS gp_create_gpo (struct gp_context *gp_ctx, const char *display_name, struct gp_object **ret)
+{
+       struct GUID guid_struct;
+       char *guid_str;
+       char *name;
+       //struct security_descriptor *sd;
+       TALLOC_CTX *mem_ctx;
+       struct gp_object *gpo;
+       unsigned int i;
+       NTSTATUS status;
+
+       /* Create a forked memory context, as a base for everything here */
+       mem_ctx = talloc_new(gp_ctx);
+
+       /* Create the gpo struct to return later */
+       gpo = talloc(gp_ctx, struct gp_object);
+
+       /* Generate GUID */
+       guid_struct = GUID_random();
+       guid_str = GUID_string(mem_ctx, &guid_struct);
+       name = talloc_asprintf(gpo, "{%s}", guid_str);
+       for (i = 0; name[i] != '\0'; i++) {
+               name[i] = toupper(name[i]);
+       }
+
+       gpo->name = name;
+       gpo->flags = 0;
+       gpo->version = 0;
+       gpo->display_name = talloc_strdup(gpo, display_name);
+       gpo->file_sys_path = talloc_asprintf(gpo, "\\\\%s\\sysvol\\%s\\Policies\\%s", lp_realm(gp_ctx->lp_ctx), lp_realm(gp_ctx->lp_ctx), name);
+
+       /* FIXME: Add gpo->security_descriptor */
+
+       /* Create the GPT */
+       status = gp_create_gpt(gp_ctx, name, gpo->file_sys_path);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to create GPT\n"));
+               return status;
+       }
+
+       /* Create matching file and DS security descriptors */
+/*     status = gp_create_gpt_security_descriptor (mem_ctx, gpo->security_descriptor, &sd);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to convert ADS security descriptor to filesystem security descriptor\n"));
+               return status;
+       }
+*/
+
+       /* Create the LDAP GPO, including CN=User and CN=Machine */
+       status = gp_create_ldap_gpo(gp_ctx, gpo);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to create LDAP group policy object\n"));
+               return status;
+       }
+
+
+       talloc_free(mem_ctx);
+
+       *ret = gpo;
+       return NT_STATUS_OK;
+}
index c02253f3775c1a71d5e99aab62e5b8a549b75642..9f45b965e4aff114cc9a9f78d08350f5fcb2fc6b 100644 (file)
@@ -61,11 +61,6 @@ struct gp_link {
        const char *dn;
 };
 
-#if 0 /* Not used yet */
-NTSTATUS gp_fetch_gpo(TALLOC_CTX *mem_ctx, struct ldb_context *ldb);
-NTSTATUS gp_apply_gpo(TALLOC_CTX *mem_ctx, struct ldb_context *ldb);
-NTSTATUS gp_check_refresh_gpo(TALLOC_CTX *mem_ctx, struct ldb_context *ldb);
-#endif
 
 NTSTATUS gp_init(TALLOC_CTX *mem_ctx,
                                struct loadparm_context *lp_ctx,
@@ -73,6 +68,7 @@ NTSTATUS gp_init(TALLOC_CTX *mem_ctx,
                                struct tevent_context *ev_ctx,
                                struct gp_context **gp_ctx);
 
+
 /* LDAP functions */
 NTSTATUS gp_list_all_gpos(struct gp_context *gp_ctx, struct gp_object ***ret);
 NTSTATUS gp_get_gplinks(struct gp_context *gp_ctx, const char *req_dn, struct gp_link ***ret);
@@ -91,7 +87,13 @@ NTSTATUS gp_del_gplink(struct gp_context *gp_ctx, const char *dn_str, const char
 NTSTATUS gp_get_inheritance(struct gp_context *gp_ctx, const char *dn_str, enum gpo_inheritance *inheritance);
 NTSTATUS gp_set_inheritance(struct gp_context *gp_ctx, const char *dn_str, enum gpo_inheritance inheritance);
 
+NTSTATUS gp_create_ldap_gpo(struct gp_context *gp_ctx, struct gp_object *gpo);
+
 /* File system functions */
-NTSTATUS gp_fetch_gpo (struct gp_context *gp_ctx, struct gp_object *gpo, const char **path);
+NTSTATUS gp_fetch_gpt (struct gp_context *gp_ctx, struct gp_object *gpo, const char **path);
+NTSTATUS gp_create_gpt(struct gp_context *gp_ctx, const char *name, const char *file_sys_path);
+
+/* Managing functions */
+NTSTATUS gp_create_gpo (struct gp_context *gp_ctx, const char *display_name, struct gp_object **ret);
 
 #endif
index d47be384cba3872a2ca58314a631bb604730f1e7..4c832efd3292d968420004c3b3a37296ed2ea69f 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 bld.SAMBA_LIBRARY('policy',
-       source='gp_ldap.c gp_filesys.c',
+       source='gp_ldap.c gp_filesys.c gp_manage.c',
        pc_files='policy.pc',
        public_deps='LIBLDB LIBSAMBA-NET',
        public_headers='policy.h',
index a990098ed97e8c37d125ea41f85b4a293072996b..4a280a239c46ff1707beea9a5587c421154060b6 100644 (file)
@@ -470,7 +470,7 @@ static int net_gpo_fetch(struct net_context *ctx, int argc, const char **argv)
                return 1;
        }
 
-       rv = gp_fetch_gpo(gp_ctx, gpo, &path);
+       rv = gp_fetch_gpt(gp_ctx, gpo, &path);
        if (!NT_STATUS_IS_OK(rv)) {
                DEBUG(0, ("Failed to fetch GPO: %s\n", get_friendly_nt_error_msg(rv)));
                return 1;
@@ -479,7 +479,38 @@ static int net_gpo_fetch(struct net_context *ctx, int argc, const char **argv)
 
        return 0;
 }
+static int net_gpo_create_usage(struct net_context *ctx, int argc, const char **argv)
+{
+       d_printf("Syntax: net gpo create <displayname> [options]\n");
+       d_printf("For a list of available options, please type net gpo create --help\n");
+       return 0;
+}
+
+static int net_gpo_create(struct net_context *ctx, int argc, const char **argv)
+{
+       struct gp_context *gp_ctx;
+       struct gp_object *gpo;
+       NTSTATUS rv;
+
+       if (argc != 1) {
+               return net_gpo_create_usage(ctx, argc, argv);
+       }
+
+       rv = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
+       if (!NT_STATUS_IS_OK(rv)) {
+               DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(rv)));
+               return 1;
+       }
+
+       rv = gp_create_gpo(gp_ctx, argv[0], &gpo);
+       if (!NT_STATUS_IS_OK(rv)) {
+               DEBUG(0, ("Failed to create GPO: %s\n", get_friendly_nt_error_msg(rv)));
+               return 1;
+       }
 
+
+       return 0;
+}
 static const struct net_functable net_gpo_functable[] = {
        { "listall", "List all GPO's on a DC\n", net_gpo_list_all, net_gpo_list_all_usage },
        { "list", "List all active GPO's for a machine/user\n", net_gpo_list, net_gpo_list_usage },
@@ -490,6 +521,7 @@ static const struct net_functable net_gpo_functable[] = {
        { "getinheritance", "Get inheritance flag from a container\n", net_gpo_inheritance_get, net_gpo_inheritance_get_usage },
        { "setinheritance", "Set inheritance flag on a container\n", net_gpo_inheritance_set, net_gpo_inheritance_set_usage },
        { "fetch", "Download a GPO\n", net_gpo_fetch, net_gpo_fetch_usage },
+       { "create", "Create a GPO\n", net_gpo_create, net_gpo_create_usage },
        { NULL, NULL }
 };