summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/lib/policy/config.mk2
-rw-r--r--source4/lib/policy/gp_filesys.c161
-rw-r--r--source4/lib/policy/gp_ldap.c140
-rw-r--r--source4/lib/policy/gp_manage.c172
-rw-r--r--source4/lib/policy/policy.h14
-rw-r--r--source4/lib/policy/wscript_build2
-rw-r--r--source4/utils/net/net_gpo.c34
7 files changed, 506 insertions, 19 deletions
diff --git a/source4/lib/policy/config.mk b/source4/lib/policy/config.mk
index 74403f8565..0a3e731c54 100644
--- a/source4/lib/policy/config.mk
+++ b/source4/lib/policy/config.mk
@@ -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
diff --git a/source4/lib/policy/gp_filesys.c b/source4/lib/policy/gp_filesys.c
index 771ba5e072..388c1d25b8 100644
--- a/source4/lib/policy/gp_filesys.c
+++ b/source4/lib/policy/gp_filesys.c
@@ -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;
+}
diff --git a/source4/lib/policy/gp_ldap.c b/source4/lib/policy/gp_ldap.c
index a7d5eb6158..b8b24d4c86 100644
--- a/source4/lib/policy/gp_ldap.c
+++ b/source4/lib/policy/gp_ldap.c
@@ -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
index 0000000000..d273678207
--- /dev/null
+++ b/source4/lib/policy/gp_manage.c
@@ -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;
+}
diff --git a/source4/lib/policy/policy.h b/source4/lib/policy/policy.h
index c02253f377..9f45b965e4 100644
--- a/source4/lib/policy/policy.h
+++ b/source4/lib/policy/policy.h
@@ -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
diff --git a/source4/lib/policy/wscript_build b/source4/lib/policy/wscript_build
index d47be384cb..4c832efd32 100644
--- a/source4/lib/policy/wscript_build
+++ b/source4/lib/policy/wscript_build
@@ -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',
diff --git a/source4/utils/net/net_gpo.c b/source4/utils/net/net_gpo.c
index a990098ed9..4a280a239c 100644
--- a/source4/utils/net/net_gpo.c
+++ b/source4/utils/net/net_gpo.c
@@ -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 }
};