Esempio n. 1
0
int proctl_service_wait(void)
{
	const char *myname = "proctl_service_wait";
	DWORD timeout = 1000 * 2, ret;
	char  ebuf[256];
	HANDLE handle_sem;

	if (__cur_handle == 0)
		return (0);

	/* Create the semaphore, with max value 32K */
	handle_sem = CreateSemaphore(NULL, 0, 32 * 1024, NULL);
	while (1) {
		ret = WaitForMultipleObjects(__cur_handle, __handles, FALSE, timeout);
		if (ret == WAIT_OBJECT_0) {
			proctl_msg_main();
		} else if (ret == WAIT_FAILED) {
			acl_msg_error("%s(%d): wait child object error(%s)",
				myname, __LINE__, acl_last_strerror(ebuf, sizeof(ebuf)));
			return (-1);
		} else if (ret != WAIT_TIMEOUT)
			break;
	}

	acl_debug(ACL_DEBUG_PROCTL, 2) ("%s(%d): __cur_handle=%d",
		myname, __LINE__, __cur_handle);
	return (0);
}
Esempio n. 2
0
static void proctl_monitor_loop(ACL_VSTREAM *sstream)
{
	const char *myname = "proctl_monitor_loop";
	ACL_VSTREAM *client;
	int   n;
	char  buf[1024];
	ACL_ARGV *cmd_argv;

	while (1) {
		client = acl_vstream_accept(sstream, NULL, 0);
		if (client == NULL)
			continue;

		n = acl_vstream_gets_nonl(client, buf, sizeof(buf));
		if (n == ACL_VSTREAM_EOF)
			continue;

		acl_debug(ACL_DEBUG_PROCTL, 2) ("%s(%d): get buf(%s)",
			myname, __LINE__, buf);
		cmd_argv = acl_argv_split(buf, "|");
		if (cmd_argv)
			proctl_monitor_main(client, cmd_argv->argc, cmd_argv->argv);
		else
			usage(client);
		acl_vstream_close(client);
	}
}
Esempio n. 3
0
static int check_access_on_dn(struct ldb_module *module,
			      TALLOC_CTX *mem_ctx,
			      struct ldb_dn *dn,
			      uint32_t access,
			      struct object_tree *tree)
{
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_result *acl_res;
	struct security_descriptor *sd = NULL;
	struct dom_sid *sid = NULL;
	NTSTATUS status;
	uint32_t access_granted;
	static const char *acl_attrs[] = {
		"nTSecurityDescriptor",
		"objectSid",
		NULL
	};

	ret = ldb_search(ldb, mem_ctx, &acl_res, dn, LDB_SCOPE_BASE, acl_attrs, NULL);
	/* we sould be able to find the parent */
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl: failed to find object %s\n", ldb_dn_get_linearized(dn)));
		return ret;
	}

	ret = get_sd_from_ldb_message(mem_ctx, acl_res->msgs[0], &sd);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	/* Theoretically we pass the check if the object has no sd */
	if (!sd) {
		return LDB_SUCCESS;
	}
	ret = get_dom_sid_from_ldb_message(mem_ctx, acl_res->msgs[0], &sid);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	status = sec_access_check_ds(sd, acl_user_token(module),
				     access,
				     &access_granted,
				     tree,
				     sid);
	if (!NT_STATUS_IS_OK(status)) {
		acl_debug(sd,
			  acl_user_token(module),
			  dn,
			  true,
			  10);
		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}
	return LDB_SUCCESS;
}
Esempio n. 4
0
static int io_close_fn(ACL_ASTREAM *astream, void *context)
{
	const char *myname = "io_close_fn";

	CLIENT_ENTRY *entry = (CLIENT_ENTRY *) context;
	ACL_VSTREAM *stream;

	stream = acl_aio_vstream(astream);
	if (stream)
		acl_debug(22, 2) ("%s: error to stream", myname);
	else
		acl_msg_error("not connected");

	forward_complete(entry);
	return (-1);
}
Esempio n. 5
0
int     name_mask_delim_opt(const char *context, const NAME_MASK *table,
		const char *names, const char *delim, int flags)
{
	const char *myname = "name_mask";
	char   *saved_names = acl_mystrdup(names);
	char   *bp = saved_names;
	int     result = 0;
	const NAME_MASK *np;
	char   *name;
	int     (*lookup) (const char *, const char *);

	if (flags & NAME_MASK_ANY_CASE)
		lookup = strcasecmp;
	else
		lookup = strcmp;

	/*
	 * Break up the names string, and look up each component in the table. If
	 * the name is found, merge its mask with the result.
	 */
	while ((name = acl_mystrtok(&bp, delim)) != 0) {
		for (np = table; /* void */ ; np++) {
			if (np->name == 0) {
				if (flags & NAME_MASK_FATAL)
					acl_msg_fatal("unknown %s value \"%s\" in \"%s\"",
							context, name, names);
				if (flags & NAME_MASK_RETURN) {
					acl_msg_warn("unknown %s value \"%s\" in \"%s\"",
							context, name, names);
					return (0);
				}
				break;
			}
			if (lookup(name, np->name) == 0) {
				acl_debug(DEBUG_NAME_MASK, 1) ("%s: %s", myname, name);
				result |= np->mask;
				break;
			}
		}
	}
	acl_myfree(saved_names);
	return (result);
}
Esempio n. 6
0
void acl_proctl_list(const char *progname)
{
	const char *myname = "acl_proctl_list";
	char  ebuf[256], buf[1024];
	ACL_VSTREAM *client;
	int   n;

	client = proctl_client_open(progname);
	n = acl_vstream_fprintf(client, "%s|-d|LIST\r\n", progname);
	if (n == ACL_VSTREAM_EOF)
		acl_msg_fatal("%s(%d): fprintf to acl_proctl error(%s)",
			myname, __LINE__, acl_last_strerror(ebuf, sizeof(ebuf)));

	while (1) {
		if (acl_vstream_gets_nonl(client, buf, sizeof(buf)) == ACL_VSTREAM_EOF)
			break;
		acl_debug(ACL_DEBUG_PROCTL, 2) ("%s(%d): buf(%s)",
			myname, __LINE__, buf);
		printf("%s\r\n", buf);
	}

	proctl_client_close(client);
}
Esempio n. 7
0
static const char *next_server_addr(CLIENT_ENTRY *entry, char *buf, size_t size)
{
	const char *myname = "next_server_addr";
	SERVICE *service = entry->service;
	int   i;

	/* 试着多连一次 */
	if (entry->ip_ntry++ > entry->dns_ctx.ip_cnt) {
		acl_msg_error("%s(%d): domain(%s), ip_ntry(%d) >= ip_cnt(%d)",
			myname, __LINE__, entry->domain_key,
			entry->ip_ntry, entry->dns_ctx.ip_cnt);
		return (NULL);
	}
	if (entry->ip_idx == entry->dns_ctx.ip_cnt)
		entry->ip_idx = 0;
	for (i = entry->ip_idx; i < entry->dns_ctx.ip_cnt; i++) {
		if (service->bind_ip_list) {
			snprintf(buf, size, "%s@%s:%d",
				service->bind_ip_list[service->bind_ip_index++],
				entry->dns_ctx.ip[i],
				entry->dns_ctx.port[i] > 0
					? entry->dns_ctx.port[i] : entry->server_port);
			if (service->bind_ip_list[service->bind_ip_index] == NULL)
				service->bind_ip_index = 0;
		} else {
			snprintf(buf, size, "%s:%d", entry->dns_ctx.ip[i],
				entry->dns_ctx.port[i] > 0
					? entry->dns_ctx.port[i] : entry->server_port);
		}
		entry->ip_idx++;
		acl_debug(23, 2) ("%s(%d): domain(%s), addr(%s)",
			myname, __LINE__, entry->domain_key, buf);
		return (buf);
	}

	return (NULL);
}
Esempio n. 8
0
static int acl_rename(struct ldb_module *module, struct ldb_request *req)
{
	int ret;
	struct ldb_dn *oldparent = ldb_dn_get_parent(req, req->op.rename.olddn);
	struct ldb_dn *newparent = ldb_dn_get_parent(req, req->op.rename.newdn);
	struct ldb_context *ldb;
	struct security_descriptor *sd = NULL;
	struct dom_sid *sid = NULL;
	struct ldb_result *acl_res;
	const struct GUID *guid;
	struct object_tree *root = NULL;
	struct object_tree *new_node = NULL;
	TALLOC_CTX *tmp_ctx = talloc_new(req);
	NTSTATUS status;
	uint32_t access_granted;
	static const char *acl_attrs[] = {
		"nTSecurityDescriptor",
		"objectClass",
		"objectSid",
		NULL
	};

	DEBUG(10, ("ldb:acl_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn)));
	if (what_is_user(module) == SECURITY_SYSTEM) {
		return ldb_next_request(module, req);
	}
	if (ldb_dn_is_special(req->op.rename.olddn)) {
		return ldb_next_request(module, req);
	}
	ldb = ldb_module_get_ctx(module);

	/* TODO search to include deleted objects */
	ret = ldb_search(ldb, req, &acl_res, req->op.rename.olddn,
			 LDB_SCOPE_BASE, acl_attrs, NULL);
	/* we sould be able to find the parent */
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl: failed to find object %s\n",
			  ldb_dn_get_linearized(req->op.rename.olddn)));
		return ret;
	}

	guid = get_oc_guid_from_message(module,acl_res->msgs[0]);
	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP,
				   &root, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	};

	guid = attribute_schemaid_guid_by_lDAPDisplayName(dsdb_get_schema(ldb),
							  "name");
	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP,
				   &new_node, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	};

	ret = get_sd_from_ldb_message(req, acl_res->msgs[0], &sd);

	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	/* Theoretically we pass the check if the object has no sd */
	if (!sd) {
		return LDB_SUCCESS;
	}
	ret = get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	status = sec_access_check_ds(sd, acl_user_token(module),
				     SEC_ADS_WRITE_PROP,
				     &access_granted,
				     root,
				     sid);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("Object %s nas no wp on name\n",
			   ldb_dn_get_linearized(req->op.rename.olddn)));
		acl_debug(sd,
			  acl_user_token(module),
			  req->op.rename.olddn,
			  true,
			  10);
		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}

	if (ldb_dn_compare(oldparent, newparent) == 0) {
		/* regular rename, not move, nothing more to do */
		return ldb_next_request(module, req);
	}

	/* What exactly to do in this case? It would fail anyway.. */
	if ((ldb_dn_compare(req->op.rename.newdn, (ldb_get_schema_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.rename.newdn, (ldb_get_config_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.rename.newdn, (ldb_get_root_basedn(ldb))) == 0)) {
		DEBUG(10,("acl:moving as an NC\n"));
		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}
	/* new parent should have create child */
	talloc_free(tmp_ctx);
	tmp_ctx = talloc_new(req);
	root = NULL;
	new_node = NULL;
	guid = get_oc_guid_from_message(module,acl_res->msgs[0]);
	if (!guid) {
		DEBUG(10,("acl:renamed object has no object class\n"));
		return ldb_module_done(req, NULL, NULL,  LDB_ERR_OPERATIONS_ERROR);
	}
	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_CREATE_CHILD,
				   &root, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ret = check_access_on_dn(module, req, newparent, SEC_ADS_CREATE_CHILD, root);
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn)));
		return ret;
	}
	/* do we have delete object on the object? */

	status = sec_access_check_ds(sd, acl_user_token(module),
				     SEC_STD_DELETE,
				     &access_granted,
				     NULL,
				     sid);

	if (NT_STATUS_IS_OK(status)) {
		return ldb_next_request(module, req);
	}
	/* what about delete child on the current parent */
	ret = check_access_on_dn(module, req, oldparent, SEC_ADS_DELETE_CHILD, NULL);
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn)));
		return ldb_module_done(req, NULL, NULL, ret);
	}
	return ldb_next_request(module, req);
}
Esempio n. 9
0
static int acl_modify(struct ldb_module *module, struct ldb_request *req)
{
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	const struct dsdb_schema *schema = dsdb_get_schema(ldb);
	int i;
	bool modify_sd = false;
	const struct GUID *guid;
	uint32_t access_granted;
	struct object_tree *root = NULL;
	struct object_tree *new_node = NULL;
	NTSTATUS status;
	struct ldb_result *acl_res;
	struct security_descriptor *sd;
	struct dom_sid *sid = NULL;
	TALLOC_CTX *tmp_ctx = talloc_new(req);
	static const char *acl_attrs[] = {
		"nTSecurityDescriptor",
		"objectClass",
		"objectSid",
		NULL
	};

	/* Don't print this debug statement if elements[0].name is going to be NULL */
	if(req->op.mod.message->num_elements > 0)
	{
		DEBUG(10, ("ldb:acl_modify: %s\n", req->op.mod.message->elements[0].name));
	}
	if (what_is_user(module) == SECURITY_SYSTEM) {
		return ldb_next_request(module, req);
	}
	if (ldb_dn_is_special(req->op.mod.message->dn)) {
		return ldb_next_request(module, req);
	}
	ret = ldb_search(ldb, req, &acl_res, req->op.mod.message->dn,
			 LDB_SCOPE_BASE, acl_attrs, NULL);

	if (ret != LDB_SUCCESS) {
		return ret;
	}

	ret = get_sd_from_ldb_message(req, acl_res->msgs[0], &sd);
	if (ret != LDB_SUCCESS) {
		DEBUG(10, ("acl_modify: cannot get descriptor\n"));
		return ret;
	}
	/* Theoretically we pass the check if the object has no sd */
	if (!sd) {
		return LDB_SUCCESS;
	}

	guid = get_oc_guid_from_message(module,acl_res->msgs[0]);
	if (!guid) {
		DEBUG(10, ("acl_modify: cannot get guid\n"));
		goto fail;
	}

	ret = get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP,
				   &root, &new_node)) {
		DEBUG(10, ("acl_modify: cannot add to object tree\n"));
		goto fail;
	}
	for (i=0; i < req->op.mod.message->num_elements; i++){
		const struct dsdb_attribute *attr;
		/* clearTextPassword is not in schema */
		if (strcmp("clearTextPassword", req->op.mod.message->elements[i].name) == 0) {
			attr = dsdb_attribute_by_lDAPDisplayName(schema, "unicodePwd");
		} else {
			attr = dsdb_attribute_by_lDAPDisplayName(schema,
								 req->op.mod.message->elements[i].name);
		}
		if (strcmp("nTSecurityDescriptor", req->op.mod.message->elements[i].name) == 0) {
			modify_sd = true;
		} else {

			if (!attr) {
				DEBUG(10, ("acl_modify: cannot find attribute %s\n",
					   req->op.mod.message->elements[i].name));
				goto fail;
			}
			if (!insert_in_object_tree(tmp_ctx,
						   &attr->attributeSecurityGUID, SEC_ADS_WRITE_PROP,
						   &new_node, &new_node)) {
				DEBUG(10, ("acl_modify: cannot add to object tree securityGUID\n"));
				goto fail;
			}

			if (!insert_in_object_tree(tmp_ctx,
						   &attr->schemaIDGUID, SEC_ADS_WRITE_PROP, &new_node, &new_node)) {
				DEBUG(10, ("acl_modify: cannot add to object tree attributeGUID\n"));
				goto fail;
			}
		}
	}

	if (root->num_of_children > 0) {
		status = sec_access_check_ds(sd, acl_user_token(module),
					     SEC_ADS_WRITE_PROP,
					     &access_granted,
					     root,
					     sid);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(10, ("Object %s nas no write property access\n",
				   ldb_dn_get_linearized(req->op.mod.message->dn)));
			acl_debug(sd,
				  acl_user_token(module),
				  req->op.mod.message->dn,
				  true,
				  10);
			talloc_free(tmp_ctx);
			return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
		}
	}
	if (modify_sd) {
		status = sec_access_check_ds(sd, acl_user_token(module),
					     SEC_STD_WRITE_DAC,
					     &access_granted,
					     NULL,
					     sid);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(10, ("Object %s nas no write dacl access\n",
				   ldb_dn_get_linearized(req->op.mod.message->dn)));
			acl_debug(sd,
				  acl_user_token(module),
				  req->op.mod.message->dn,
				  true,
				  10);
			talloc_free(tmp_ctx);
			return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
		}
	}

	talloc_free(tmp_ctx);
	return ldb_next_request(module, req);
fail:
	talloc_free(tmp_ctx);
	return LDB_ERR_OPERATIONS_ERROR;
}
Esempio n. 10
0
static int connect_timeout_callback(ACL_ASTREAM *astream, void *context)
{
	const char* myname = "connect_timeout_callback";
	CLIENT_ENTRY *entry = (CLIENT_ENTRY *) context;

	/* 卸载回调函数,防止被重复调用 */
	acl_aio_ctl(astream,
		ACL_AIO_CTL_CONNECT_FN, NULL,
		ACL_AIO_CTL_CLOSE_HOOK_DEL, connect_close_callback, entry,
		ACL_AIO_CTL_TIMEO_HOOK_DEL, connect_timeout_callback, entry,
		ACL_AIO_CTL_END);

	if (entry->flag_has_replied == 1)
		return (-1);

	if (entry->ip_idx < entry->dns_ctx.ip_cnt) {
		ACL_ASTREAM *server;

		acl_debug(23, 1) ("%s(%d): begin to connect next ip(%s:%d)",
			myname, __LINE__, entry->dns_ctx.ip[entry->ip_idx],
			entry->server_port);

		/* 断开与服务端的连接,但保持与浏览器端的连接
		 * XXX: 因为该函数将清除一些关闭回调函数,不知是否会造成某些内存泄漏?
		 * 注,此处并不关闭服务端连接,需要调用者自己来关闭
		 */
		if (client_entry_detach(entry, acl_aio_vstream(entry->server)) == 1) {
			acl_debug(3, 1) ("%s(%d): entry is freed", myname, __LINE__);
			return (-1);
		}

		server = forward_connect_next(entry);
		if (server == NULL)
			goto CONNECT_ERROR;

		client_entry_set_server(entry, server);
		acl_aio_ctl(server,
			ACL_AIO_CTL_CONNECT_FN, connect_callback,
			ACL_AIO_CTL_CLOSE_HOOK_ADD, connect_close_callback, entry,
			ACL_AIO_CTL_TIMEO_HOOK_ADD, connect_timeout_callback, entry,
			ACL_AIO_CTL_CTX, entry,
			ACL_AIO_CTL_END);

		/* 通过返回-1,使异步流框架关闭服务端连接 */
		return (-1);
	}

CONNECT_ERROR:

	entry->tm.connect = time(NULL) - entry->tm.stamp;
	if (entry->ip_idx <= 0)
		acl_debug(23, 0) ("%s(%d): internal error, ip_idx=0, domain(%s:%d)",
			myname, __LINE__, entry->domain_key, entry->server_port);
	else
		acl_debug(23, 0) ("%s(%d): connect timeout, addr(%s:%d)",
			myname, __LINE__,
			entry->dns_ctx.ip[entry->ip_idx - 1],
			entry->server_port);

	entry->flag_has_replied = 1;

	if (entry->connect_timeout_fn)
		entry->connect_timeout_fn(entry);

	return (-1);
}
Esempio n. 11
0
int     mac_parse(const char *value, MAC_PARSE_FN action, char *context)
{
    const char *myname = "mac_parse";
    ACL_VSTRING *buf = acl_vstring_alloc(1);	/* result buffer */
    const char *vp;			/* value pointer */
    const char *pp;			/* open_paren pointer */
    const char *ep;			/* string end pointer */
    static char open_paren[] = "({";
    static char close_paren[] = ")}";
    int     level;
    int     status = 0;

#define SKIP(start, var, cond) \
        for (var = start; *var && (cond); var++);

    acl_debug(DEBUG_MAC, 2) ("%s: %s", myname, value);

    for (vp = value; *vp;) {
	if (*vp != '$') {			/* ordinary character */
	    ACL_VSTRING_ADDCH(buf, *vp);
	    vp += 1;
	} else if (vp[1] == '$') {		/* $$ becomes $ */
	    ACL_VSTRING_ADDCH(buf, *vp);
	    vp += 2;
	} else {				/* found bare $ */
	    if (ACL_VSTRING_LEN(buf) > 0)
		MAC_PARSE_ACTION(status, MAC_PARSE_LITERAL, buf, context);
	    vp += 1;
	    pp = open_paren;
	    if (*vp == *pp || *vp == *++pp) {	/* ${x} or $(x) */
		level = 1;
		vp += 1;
		for (ep = vp; level > 0; ep++) {
		    if (*ep == 0) {
			acl_msg_warn("truncated macro reference: \"%s\"", value);
			status |= MAC_PARSE_ERROR;
			break;
		    }
		    if (*ep == *pp)
			level++;
		    if (*ep == close_paren[pp - open_paren])
			level--;
		}
		if (status & MAC_PARSE_ERROR)
		    break;
		acl_vstring_strncat(buf, vp, level > 0 ? ep - vp : ep - vp - 1);
		vp = ep;
	    } else {				/* plain $x */
		SKIP(vp, ep, ACL_ISALNUM(*ep) || *ep == '_');
		acl_vstring_strncat(buf, vp, ep - vp);
		vp = ep;
	    }
	    if (ACL_VSTRING_LEN(buf) == 0) {
		status |= MAC_PARSE_ERROR;
		acl_msg_warn("empty macro name: \"%s\"", value);
		break;
	    }
	    MAC_PARSE_ACTION(status, MAC_PARSE_EXPR, buf, context);
	}
    }
    if (ACL_VSTRING_LEN(buf) > 0 && (status & MAC_PARSE_ERROR) == 0)
	MAC_PARSE_ACTION(status, MAC_PARSE_LITERAL, buf, context);

    /*
     * Cleanup.
     */
    acl_vstring_free(buf);

    return (status);
}