Beispiel #1
0
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;
	NTSTATUS status;

	/* Create a forked memory context, as a base for everything here */
	mem_ctx = talloc_new(gp_ctx);
	NT_STATUS_HAVE_NO_MEMORY(mem_ctx);

	/* Create the gpo struct to return later */
	gpo = talloc(gp_ctx, struct gp_object);
	if (gpo == NULL) {
		TALLOC_FREE(mem_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* Generate a GUID */
	guid_struct = GUID_random();
	guid_str = GUID_string2(mem_ctx, &guid_struct);
	if (guid_str == NULL) {
		TALLOC_FREE(mem_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	name = strupper_talloc(mem_ctx, guid_str);
	if (name == NULL) {
		TALLOC_FREE(mem_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* Prepare the GPO struct */
	gpo->dn = NULL;
	gpo->name = name;
	gpo->flags = 0;
	gpo->version = 0;
	gpo->display_name = talloc_strdup(gpo, display_name);
	if (gpo->display_name == NULL) {
		TALLOC_FREE(mem_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	gpo->file_sys_path = talloc_asprintf(gpo, "\\\\%s\\sysvol\\%s\\Policies\\%s", lpcfg_dnsdomain(gp_ctx->lp_ctx), lpcfg_dnsdomain(gp_ctx->lp_ctx), name);
	if (gpo->file_sys_path == NULL) {
		TALLOC_FREE(mem_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* 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"));
		talloc_free(mem_ctx);
		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"));
		talloc_free(mem_ctx);
		return status;
	}

	/* Get the new security descriptor */
	status = gp_get_gpo_info(gp_ctx, gpo->dn, &gpo);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to fetch LDAP group policy object\n"));
		talloc_free(mem_ctx);
		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"));
		talloc_free(mem_ctx);
		return status;
	}

	/* Set the security descriptor on the filesystem for this GPO */
	status = gp_set_gpt_security_descriptor(gp_ctx, gpo, sd);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to set security descriptor (ACL) on the file system\n"));
		talloc_free(mem_ctx);
		return status;
	}

	talloc_free(mem_ctx);

	*ret = gpo;
	return NT_STATUS_OK;
}
Beispiel #2
0
static char *sdap_sudo_build_host_filter(TALLOC_CTX *mem_ctx,
                                         struct sdap_attr_map *map,
                                         char **hostnames,
                                         char **ip_addr,
                                         bool netgroups,
                                         bool regexp)
{
    TALLOC_CTX *tmp_ctx = NULL;
    char *filter = NULL;
    int i;

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
        return NULL;
    }

    filter = talloc_strdup(tmp_ctx, "(|");
    if (filter == NULL) {
        goto done;
    }

    /* sudoHost is not specified */
    filter = talloc_asprintf_append_buffer(filter, "(!(%s=*))",
                                           map[SDAP_AT_SUDO_HOST].name);
    if (filter == NULL) {
        goto done;
    }

    /* ALL */
    filter = talloc_asprintf_append_buffer(filter, "(%s=ALL)",
                                           map[SDAP_AT_SUDO_HOST].name);
    if (filter == NULL) {
        goto done;
    }

    /* hostnames */
    if (hostnames != NULL) {
        for (i = 0; hostnames[i] != NULL; i++) {
            filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
                                                   map[SDAP_AT_SUDO_HOST].name,
                                                   hostnames[i]);
            if (filter == NULL) {
                goto done;
            }
        }
    }

    /* ip addresses and networks */
    if (ip_addr != NULL) {
        for (i = 0; ip_addr[i] != NULL; i++) {
            filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
                                                   map[SDAP_AT_SUDO_HOST].name,
                                                   ip_addr[i]);
            if (filter == NULL) {
                goto done;
            }
        }
    }

    /* sudoHost contains netgroup - will be filtered more by sudo */
    if (netgroups) {
        filter = talloc_asprintf_append_buffer(filter, SDAP_SUDO_FILTER_NETGROUP,
                                               map[SDAP_AT_SUDO_HOST].name,
                                               "*");
        if (filter == NULL) {
            goto done;
        }
    }

    /* sudoHost contains regexp - will be filtered more by sudo */
    /* from sudo match.c :
     * #define has_meta(s)  (strpbrk(s, "\\?*[]") != NULL)
     */
    if (regexp) {
        filter = talloc_asprintf_append_buffer(filter,
                                               "(|(%s=*\\\\*)(%s=*?*)(%s=*\\2A*)"
                                                 "(%s=*[*]*))",
                                               map[SDAP_AT_SUDO_HOST].name,
                                               map[SDAP_AT_SUDO_HOST].name,
                                               map[SDAP_AT_SUDO_HOST].name,
                                               map[SDAP_AT_SUDO_HOST].name);
        if (filter == NULL) {
            goto done;
        }
    }

    filter = talloc_strdup_append_buffer(filter, ")");
    if (filter == NULL) {
        goto done;
    }

    talloc_steal(mem_ctx, filter);

done:
    talloc_free(tmp_ctx);

    return filter;
}
Beispiel #3
0
/* XXX: This function really should be in libldb's pyldb.c */
static PyObject *py_ldb_set_opaque_integer(PyObject *self, PyObject *args)
{
	int value;
	int *old_val, *new_val;
	char *py_opaque_name, *opaque_name_talloc;
	struct ldb_context *ldb;
	int ret;
	TALLOC_CTX *tmp_ctx;

	if (!PyArg_ParseTuple(args, "si", &py_opaque_name, &value))
		return NULL;

	ldb = pyldb_Ldb_AsLdbContext(self);

	/* see if we have a cached copy */
	old_val = (int *)ldb_get_opaque(ldb, py_opaque_name);
	/* XXX: We shouldn't just blindly assume that the value that is 
	 * already present has the size of an int and is not shared 
	 * with other code that may rely on it not changing. 
	 * JRV 20100403 */

	if (old_val) {
		*old_val = value;
		Py_RETURN_NONE;
	}

	tmp_ctx = talloc_new(ldb);
	if (tmp_ctx == NULL) {
		PyErr_NoMemory();
		return NULL;
	}

	new_val = talloc(tmp_ctx, int);
	if (new_val == NULL) {
		talloc_free(tmp_ctx);
		PyErr_NoMemory();
		return NULL;
	}

	opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
	if (opaque_name_talloc == NULL) {
		talloc_free(tmp_ctx);
		PyErr_NoMemory();
		return NULL;
	}

	*new_val = value;

	/* cache the domain_sid in the ldb */
	ret = ldb_set_opaque(ldb, opaque_name_talloc, new_val);

	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		PyErr_SetLdbError(py_ldb_error, ret, ldb);
		return NULL;
	}

	talloc_steal(ldb, new_val);
	talloc_steal(ldb, opaque_name_talloc);
	talloc_free(tmp_ctx);

	Py_RETURN_NONE;
}
Beispiel #4
0
/*
  work out the principal to use for DRS replication connections
 */
NTSTATUS dreplsrv_get_target_principal(struct dreplsrv_service *s,
				       TALLOC_CTX *mem_ctx,
				       const struct repsFromTo1 *rft,
				       const char **target_principal)
{
	TALLOC_CTX *tmp_ctx;
	struct ldb_result *res;
	const char *attrs[] = { "dNSHostName", NULL };
	int ret;
	const char *hostname;
	struct ldb_dn *dn;
	struct ldb_dn *forest_dn;

	*target_principal = NULL;

	tmp_ctx = talloc_new(mem_ctx);

	/* we need to find their hostname */
	ret = dsdb_find_dn_by_guid(s->samdb, tmp_ctx, &rft->source_dsa_obj_guid, &dn);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		/* its OK for their NTDSDSA DN not to be in our database */
		return NT_STATUS_OK;
	}

	/* strip off the NTDS Settings */
	if (!ldb_dn_remove_child_components(dn, 1)) {
		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, dn, attrs, 0);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		/* its OK for their account DN not to be in our database */
		return NT_STATUS_OK;
	}

	hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
	if (hostname == NULL) {
		talloc_free(tmp_ctx);
		/* its OK to not have a dnshostname */
		return NT_STATUS_OK;
	}

	/* All DCs have the GC/hostname/realm name, but if some of the
	 * preconditions are not satisfied, then we will fall back to
	 * the
	 * E3514235-4B06-11D1-AB04-00C04FC2DCD2/${NTDSGUID}/${DNSDOMAIN}
	 * name.  This means that if a AD server has a dnsHostName set
	 * on it's record, it must also have GC/hostname/realm
	 * servicePrincipalName */

	forest_dn = ldb_get_root_basedn(s->samdb);
	if (forest_dn == NULL) {
		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	*target_principal = talloc_asprintf(mem_ctx, "GC/%s/%s",
					    hostname,
					    samdb_dn_to_dns_domain(tmp_ctx, forest_dn));
	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
}
Beispiel #5
0
static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security,
					 TALLOC_CTX *mem_ctx_out,
					 struct auth_session_info **_session_info) 
{
	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
	struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
	krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
	struct auth_user_info_dc *user_info_dc = NULL;
	struct auth_session_info *session_info = NULL;
	struct PAC_LOGON_INFO *logon_info;

	krb5_principal client_principal;
	char *principal_string;
	
	DATA_BLOB pac;
	krb5_data pac_data;

	krb5_error_code ret;

	TALLOC_CTX *mem_ctx = talloc_new(mem_ctx_out);
	if (!mem_ctx) {
		return NT_STATUS_NO_MEMORY;
	}
	
	ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal);
	if (ret) {
		DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", 
			  smb_get_krb5_error_message(context, 
						     ret, mem_ctx)));
		talloc_free(mem_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	
	ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context, 
				client_principal, &principal_string);
	if (ret) {
		DEBUG(1, ("Unable to parse client principal: %s\n",
			  smb_get_krb5_error_message(context, 
						     ret, mem_ctx)));
		krb5_free_principal(context, client_principal);
		talloc_free(mem_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	ret = krb5_ticket_get_authorization_data_type(context, gensec_krb5_state->ticket, 
						      KRB5_AUTHDATA_WIN2K_PAC, 
						      &pac_data);
	
	if (ret && gensec_setting_bool(gensec_security->settings, "gensec", "require_pac", false)) {
		DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s \n",
			  principal_string,
			  smb_get_krb5_error_message(context, 
						     ret, mem_ctx)));
		free(principal_string);
		krb5_free_principal(context, client_principal);
		talloc_free(mem_ctx);
		return NT_STATUS_ACCESS_DENIED;
	} else if (ret) {
		/* NO pac */
		DEBUG(5, ("krb5_ticket_get_authorization_data_type failed to find PAC: %s\n", 
			  smb_get_krb5_error_message(context, 
						     ret, mem_ctx)));
		if (gensec_security->auth_context && 
		    !gensec_setting_bool(gensec_security->settings, "gensec", "require_pac", false)) {
			DEBUG(1, ("Unable to find PAC for %s, resorting to local user lookup: %s",
				  principal_string, smb_get_krb5_error_message(context, 
						     ret, mem_ctx)));
			nt_status = gensec_security->auth_context->get_user_info_dc_principal(mem_ctx,
											     gensec_security->auth_context, 
											     principal_string,
											     NULL, &user_info_dc);
			if (!NT_STATUS_IS_OK(nt_status)) {
				free(principal_string);
				krb5_free_principal(context, client_principal);
				talloc_free(mem_ctx);
				return nt_status;
			}
		} else {
			DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access\n",
				  principal_string));
			free(principal_string);
			krb5_free_principal(context, client_principal);
			talloc_free(mem_ctx);
			return NT_STATUS_ACCESS_DENIED;
		}
	} else {
		/* Found pac */
		union netr_Validation validation;

		pac = data_blob_talloc(mem_ctx, pac_data.data, pac_data.length);
		if (!pac.data) {
			free(principal_string);
			krb5_free_principal(context, client_principal);
			talloc_free(mem_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		/* decode and verify the pac */
		nt_status = kerberos_pac_logon_info(gensec_krb5_state, 
						    pac,
						    gensec_krb5_state->smb_krb5_context->krb5_context,
						    NULL, gensec_krb5_state->keyblock,
						    client_principal,
						    gensec_krb5_state->ticket->ticket.authtime, &logon_info);

		if (!NT_STATUS_IS_OK(nt_status)) {
			free(principal_string);
			krb5_free_principal(context, client_principal);
			talloc_free(mem_ctx);
			return nt_status;
		}

		validation.sam3 = &logon_info->info3;
		nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
								 NULL,
								 3, &validation,
								  true, /* This user was authenticated */
								 &user_info_dc);
		if (!NT_STATUS_IS_OK(nt_status)) {
			free(principal_string);
			krb5_free_principal(context, client_principal);
			talloc_free(mem_ctx);
			return nt_status;
		}
	}

	free(principal_string);
	krb5_free_principal(context, client_principal);

	/* references the user_info_dc into the session_info */
	nt_status = gensec_generate_session_info(mem_ctx, gensec_security, user_info_dc, &session_info);

	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(mem_ctx);
		return nt_status;
	}

	nt_status = gensec_krb5_session_key(gensec_security, session_info, &session_info->session_key);

	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(mem_ctx);
		return nt_status;
	}

	*_session_info = talloc_steal(mem_ctx_out, session_info);

	talloc_free(mem_ctx);
	return NT_STATUS_OK;
}
/*
  convert a filename from a share relative path, to a path in the
  snapshot directory
 */
static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname, const char *gmt_path)
{
	TALLOC_CTX *tmp_ctx = talloc_new(handle->data);
	const char *snapdir, *relpath, *baseoffset, *basedir;
	size_t baselen;
	char *ret, *prefix;

	struct tm timestamp;
	time_t timestamp_t;
	char snapshot[MAXPATHLEN];
	const char *fmt;

	fmt = lp_parm_const_string(SNUM(handle->conn), "shadow",
				   "format", SHADOW_COPY2_DEFAULT_FORMAT);

	snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle);
	if (snapdir == NULL) {
		DEBUG(2,("no snapdir found for share at %s\n", handle->conn->connectpath));
		talloc_free(tmp_ctx);
		return NULL;
	}

	basedir = shadow_copy2_find_basedir(tmp_ctx, handle);
	if (basedir == NULL) {
		DEBUG(2,("no basedir found for share at %s\n", handle->conn->connectpath));
		talloc_free(tmp_ctx);
		return NULL;
	}

	prefix = talloc_asprintf(tmp_ctx, "%s/@GMT-", snapdir);
	if (strncmp(fname, prefix, (talloc_get_size(prefix)-1)) == 0) {
		/* this looks like as we have already normalized it, leave it untouched*/
		talloc_free(tmp_ctx);
		return talloc_strdup(handle->data, fname);
	}

	if (strncmp(fname, "@GMT-", 5) != 0) {
		fname = shadow_copy2_normalise_path(tmp_ctx, fname, gmt_path);
		if (fname == NULL) {
			talloc_free(tmp_ctx);
			return NULL;
		}
	}

	ZERO_STRUCT(timestamp);
	relpath = strptime(fname, SHADOW_COPY2_GMT_FORMAT, &timestamp);
	if (relpath == NULL) {
		talloc_free(tmp_ctx);
		return NULL;
	}

	/* relpath is the remaining portion of the path after the @GMT-xxx */

	if (lp_parm_bool(SNUM(handle->conn), "shadow", "localtime",
			 SHADOW_COPY2_DEFAULT_LOCALTIME))
	{
		timestamp_t = timegm(&timestamp);
		localtime_r(&timestamp_t, &timestamp);
	}

	strftime(snapshot, MAXPATHLEN, fmt, &timestamp);

	baselen = strlen(basedir);
	baseoffset = handle->conn->connectpath + baselen;

	/* some sanity checks */
	if (strncmp(basedir, handle->conn->connectpath, baselen) != 0 ||
	    (handle->conn->connectpath[baselen] != 0 && handle->conn->connectpath[baselen] != '/')) {
		DEBUG(0,("convert_shadow2_name: basedir %s is not a parent of %s\n",
			 basedir, handle->conn->connectpath));
		talloc_free(tmp_ctx);
		return NULL;
	}

	if (*relpath == '/') relpath++;
	if (*baseoffset == '/') baseoffset++;

	ret = talloc_asprintf(handle->data, "%s/%s/%s/%s",
			      snapdir, 
			      snapshot,
			      baseoffset, 
			      relpath);
	DEBUG(6,("convert_shadow2_name: '%s' -> '%s'\n", fname, ret));
	talloc_free(tmp_ctx);
	return ret;
}
Beispiel #7
0
static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context,
						       struct tevent_context *ev,
						       krb5_krbhst_info *hi,
						       struct addrinfo *ai,
						       krb5_send_to_kdc_func func,
						       void *data,
						       time_t timeout,
						       const krb5_data *send_buf,
						       krb5_data *recv_buf)
{
	krb5_error_code ret;
	NTSTATUS status;
	const char *name;
	struct addrinfo *a;
	struct smb_krb5_socket *smb_krb5;

	DATA_BLOB send_blob;

	TALLOC_CTX *tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) {
		return ENOMEM;
	}

	send_blob = data_blob_const(send_buf->data, send_buf->length);

	for (a = ai; a; a = a->ai_next) {
		struct socket_address *remote_addr;
		smb_krb5 = talloc(tmp_ctx, struct smb_krb5_socket);
		if (!smb_krb5) {
			talloc_free(tmp_ctx);
			return ENOMEM;
		}
		smb_krb5->hi = hi;

		switch (a->ai_family) {
		case PF_INET:
			name = "ipv4";
			break;
#ifdef HAVE_IPV6
		case PF_INET6:
			name = "ipv6";
			break;
#endif
		default:
			talloc_free(tmp_ctx);
			return EINVAL;
		}

		status = NT_STATUS_INVALID_PARAMETER;
		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			status = socket_create(name, SOCKET_TYPE_DGRAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_TCP:
			status = socket_create(name, SOCKET_TYPE_STREAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(tmp_ctx);
			return EINVAL;
		}
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}

		talloc_steal(smb_krb5, smb_krb5->sock);

		remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen);
		if (!remote_addr) {
			talloc_free(smb_krb5);
			continue;
		}

		status = socket_connect_ev(smb_krb5->sock, NULL, remote_addr, 0, ev);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}

		/* Setup the FDE, start listening for read events
		 * from the start (otherwise we may miss a socket
		 * drop) and mark as AUTOCLOSE along with the fde */

		/* Ths is equivilant to EVENT_FD_READABLE(smb_krb5->fde) */
		smb_krb5->fde = tevent_add_fd(ev, smb_krb5->sock,
					      socket_get_fd(smb_krb5->sock),
					      TEVENT_FD_READ,
					      smb_krb5_socket_handler, smb_krb5);
		/* its now the job of the event layer to close the socket */
		tevent_fd_set_close_fn(smb_krb5->fde, socket_tevent_fd_close_fn);
		socket_set_flags(smb_krb5->sock, SOCKET_FLAG_NOCLOSE);

		tevent_add_timer(ev, smb_krb5,
				 timeval_current_ofs(timeout, 0),
				 smb_krb5_request_timeout, smb_krb5);

		smb_krb5->status = NT_STATUS_OK;
		smb_krb5->reply = data_blob(NULL, 0);

		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			TEVENT_FD_WRITEABLE(smb_krb5->fde);
			smb_krb5->request = send_blob;
			break;
		case KRB5_KRBHST_TCP:

			smb_krb5->packet = packet_init(smb_krb5);
			if (smb_krb5->packet == NULL) {
				talloc_free(smb_krb5);
				return ENOMEM;
			}
			packet_set_private(smb_krb5->packet, smb_krb5);
			packet_set_socket(smb_krb5->packet, smb_krb5->sock);
			packet_set_callback(smb_krb5->packet, smb_krb5_full_packet);
			packet_set_full_request(smb_krb5->packet, packet_full_request_u32);
			packet_set_error_handler(smb_krb5->packet, smb_krb5_error_handler);
			packet_set_event_context(smb_krb5->packet, ev);
			packet_set_fde(smb_krb5->packet, smb_krb5->fde);

			smb_krb5->request = data_blob_talloc(smb_krb5, NULL, send_blob.length + 4);
			RSIVAL(smb_krb5->request.data, 0, send_blob.length);
			memcpy(smb_krb5->request.data+4, send_blob.data, send_blob.length);
			packet_send(smb_krb5->packet, smb_krb5->request);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(tmp_ctx);
			return EINVAL;
		}
		while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) {
			if (tevent_loop_once(ev) != 0) {
				talloc_free(tmp_ctx);
				return EINVAL;
			}

                        if (func) {
				/* After each and every event loop, reset the
				 * send_to_kdc pointers to what they were when
				 * we entered this loop.  That way, if a
				 * nested event has invalidated them, we put
				 * it back before we return to the heimdal
				 * code */
				ret = krb5_set_send_to_kdc_func(context,
								func,
								data);
				if (ret != 0) {
					talloc_free(tmp_ctx);
					return ret;
				}
			}
		}
		if (NT_STATUS_EQUAL(smb_krb5->status, NT_STATUS_IO_TIMEOUT)) {
			talloc_free(smb_krb5);
			continue;
		}

		if (!NT_STATUS_IS_OK(smb_krb5->status)) {
			struct tsocket_address *addr = socket_address_to_tsocket_address(smb_krb5, remote_addr);
			const char *addr_string = NULL;
			if (addr) {
				addr_string = tsocket_address_inet_addr_string(addr, smb_krb5);
			} else {
				addr_string = NULL;
			}
			DEBUG(2,("Error reading smb_krb5 reply packet: %s from %s\n", nt_errstr(smb_krb5->status),
				 addr_string));
			talloc_free(smb_krb5);
			continue;
		}

		ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length);
		if (ret) {
			talloc_free(tmp_ctx);
			return ret;
		}
		talloc_free(smb_krb5);

		break;
	}
	talloc_free(tmp_ctx);
	if (a) {
		return 0;
	}
	return KRB5_KDC_UNREACH;
}
Beispiel #8
0
/* 
   basic testing of SMB2 connection calls
*/
bool torture_smb2_connect(struct torture_context *torture)
{
	TALLOC_CTX *mem_ctx = talloc_new(NULL);
	struct smb2_tree *tree;
	struct smb2_request *req;
	struct smb2_handle h1, h2;
	NTSTATUS status;

	if (!torture_smb2_connection(torture, &tree)) {
		return false;
	}

	smb2_util_unlink(tree, "test9.dat");

	h1 = torture_smb2_createfile(tree, "test9.dat");
	h2 = torture_smb2_createfile(tree, "test9.dat");
	status = torture_smb2_write(torture, tree, h1);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Write failed - %s\n", nt_errstr(status));
		return false;
	}
	status = torture_smb2_close(tree, h1);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Close failed - %s\n", nt_errstr(status));
		return false;
	}
	status = torture_smb2_close(tree, h2);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Close failed - %s\n", nt_errstr(status));
		return false;
	}

	status = smb2_util_close(tree, h1);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
		printf("close should have closed the handle - %s\n", nt_errstr(status));
		return false;
	}

	status = smb2_tdis(tree);
	if (!NT_STATUS_IS_OK(status)) {
		printf("tdis failed - %s\n", nt_errstr(status));
		return false;
	}

	status = smb2_tdis(tree);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
		printf("tdis should have disabled session - %s\n", nt_errstr(status));
		return false;
	}

 	status = smb2_logoff(tree->session);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Logoff failed - %s\n", nt_errstr(status));
		return false;
	}

	req = smb2_logoff_send(tree->session);
	if (!req) {
		printf("smb2_logoff_send() failed\n");
		return false;
	}

	req->session = NULL;

	status = smb2_logoff_recv(req);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
		printf("Logoff should have disabled session - %s\n", nt_errstr(status));
		return false;
	}

	status = smb2_keepalive(tree->session->transport);
	if (!NT_STATUS_IS_OK(status)) {
		printf("keepalive failed? - %s\n", nt_errstr(status));
		return false;
	}

	talloc_free(mem_ctx);

	return true;
}
Beispiel #9
0
/*
  handle recv events on a nbt dgram socket
*/
static void dgm_socket_recv(struct nbt_dgram_socket *dgmsock)
{
	TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
	NTSTATUS status;
	struct socket_address *src;
	DATA_BLOB blob;
	size_t nread, dsize;
	struct nbt_dgram_packet *packet;
	const char *mailslot_name;
	enum ndr_err_code ndr_err;

	status = socket_pending(dgmsock->sock, &dsize);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return;
	}

	blob = data_blob_talloc(tmp_ctx, NULL, dsize);
	if (blob.data == NULL) {
		talloc_free(tmp_ctx);
		return;
	}

	status = socket_recvfrom(dgmsock->sock, blob.data, blob.length, &nread,
				 tmp_ctx, &src);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return;
	}
	blob.length = nread;

	DEBUG(2,("Received dgram packet of length %d from %s:%d\n", 
		 (int)blob.length, src->addr, src->port));

	packet = talloc(tmp_ctx, struct nbt_dgram_packet);
	if (packet == NULL) {
		talloc_free(tmp_ctx);
		return;
	}

	/* parse the request */
	ndr_err = ndr_pull_struct_blob(&blob, packet, dgmsock->iconv_convenience, packet,
				      (ndr_pull_flags_fn_t)ndr_pull_nbt_dgram_packet);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(2,("Failed to parse incoming NBT DGRAM packet - %s\n",
			 nt_errstr(status)));
		talloc_free(tmp_ctx);
		return;
	}

	/* if this is a mailslot message, then see if we can dispatch it to a handler */
	mailslot_name = dgram_mailslot_name(packet);
	if (mailslot_name) {
		struct dgram_mailslot_handler *dgmslot;
		dgmslot = dgram_mailslot_find(dgmsock, mailslot_name);
		if (dgmslot) {
			dgmslot->handler(dgmslot, packet, src);
		} else {
			DEBUG(2,("No mailslot handler for '%s'\n", mailslot_name));
		}
	} else {
		/* dispatch if there is a general handler */
		if (dgmsock->incoming.handler) {
			dgmsock->incoming.handler(dgmsock, packet, src);
		}
	}

	talloc_free(tmp_ctx);
}
Beispiel #10
0
/* allocate a RID using our RID Set
   If we run out of RIDs then allocate a new pool
   either locally or by contacting the RID Manager
*/
int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid, struct ldb_request *parent)
{
	struct ldb_context *ldb;
	int ret;
	struct ldb_dn *rid_set_dn;
	struct ldb_result *res;
	struct ldb_message *msg;
	struct ridalloc_ridset_values oridset;
	struct ridalloc_ridset_values nridset;
	uint32_t prev_pool_lo, prev_pool_hi;
	TALLOC_CTX *tmp_ctx = talloc_new(module);

	(*rid) = 0;
	ldb = ldb_module_get_ctx(module);

	ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn, parent);
	}
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
				    ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return ret;
	}

	ridalloc_get_ridset_values(res->msgs[0], &oridset);
	if (oridset.alloc_pool == UINT64_MAX) {
		ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	nridset = oridset;

	/*
	 * If we never used a pool, setup out first pool
	 */
	if (nridset.prev_pool == UINT64_MAX ||
	    nridset.next_rid == UINT32_MAX) {
		nridset.prev_pool = nridset.alloc_pool;
		nridset.next_rid = nridset.prev_pool & 0xFFFFFFFF;
	}

	/*
	 * Now check if our current pool is still usable
	 */
	nridset.next_rid += 1;
	prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
	prev_pool_hi = nridset.prev_pool >> 32;
	if (nridset.next_rid > prev_pool_hi) {
		/*
		 * We need a new pool, check if we already have a new one
		 * Otherwise we need to get a new pool.
		 */
		if (nridset.alloc_pool == nridset.prev_pool) {
			/*
			 * if we are the RID Manager,
			 * we can get a new pool localy.
			 * Otherwise we fail the operation and
			 * ask async for a new pool.
			 */
			ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
			if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
				ridalloc_poke_rid_manager(module);
				talloc_free(tmp_ctx);
				return ret;
			}
			if (ret != LDB_SUCCESS) {
				talloc_free(tmp_ctx);
				return ret;
			}
		}

		/*
		 * increment the rIDUsedPool attribute
		 *
		 * Note: w2k8r2 doesn't update this attribute,
		 *       at least if it's itself the rid master.
		 */
		nridset.used_pool += 1;

		/* now use the new pool */
		nridset.prev_pool = nridset.alloc_pool;
		prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
		prev_pool_hi = nridset.prev_pool >> 32;
		nridset.next_rid = prev_pool_lo;
	}

	if (nridset.next_rid < prev_pool_lo || nridset.next_rid > prev_pool_hi) {
		ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
				       (unsigned)nridset.next_rid,
				       (unsigned)prev_pool_lo,
				       (unsigned)prev_pool_hi);
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/*
	 * if we are half-exhausted then try to get a new pool.
	 */
	if (nridset.next_rid > (prev_pool_hi + prev_pool_lo)/2) {
		/*
		 * if we are the RID Manager,
		 * we can get a new pool localy.
		 * Otherwise we fail the operation and
		 * ask async for a new pool.
		 */
		ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
		if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
			ridalloc_poke_rid_manager(module);
			ret = LDB_SUCCESS;
		}
		if (ret != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return ret;
		}
	}

	/*
	 * update the values
	 */
	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		return ldb_module_oom(module);
	}
	msg->dn = rid_set_dn;

	ret = ridalloc_set_ridset_values(module, msg,
					 &oridset, &nridset);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_free(tmp_ctx);
	*rid = nridset.next_rid;
	return LDB_SUCCESS;
}
Beispiel #11
0
/*
  called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
 */
int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop,
				    struct ldb_request *parent)
{
	struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
	struct ldb_dn *rid_manager_dn;
	TALLOC_CTX *tmp_ctx = talloc_new(module);
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_result *res;
	struct ldb_message *msg;
	struct ridalloc_ridset_values oridset, nridset;

	ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
				       GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
	if (!server_dn) {
		talloc_free(tmp_ctx);
		return ldb_module_oom(module);
	}

	ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
				       ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn, parent);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn, parent);
		talloc_free(tmp_ctx);
		return ret;
	}

	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
				       ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
				    ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return ret;
	}

	ridalloc_get_ridset_values(res->msgs[0], &oridset);
	if (oridset.alloc_pool == UINT64_MAX) {
		ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	nridset = oridset;

	if (exop->fsmo_info != 0) {

		if (nridset.alloc_pool != exop->fsmo_info) {
			/* it has already been updated */
			DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
				 (unsigned long long)exop->fsmo_info,
				 (unsigned long long)nridset.alloc_pool));
			talloc_free(tmp_ctx);
			return LDB_SUCCESS;
		}
	}

	/* grab a pool from the RID Manager object */
	ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &nridset.alloc_pool, parent);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	/*
	 * update the values
	 */
	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		return ldb_module_oom(module);
	}
	msg->dn = rid_set_dn;

	ret = ridalloc_set_ridset_values(module, msg,
					 &oridset, &nridset);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
				       ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
Beispiel #12
0
/*
  create a RID Set object for the specified DC
 */
static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
					struct ldb_dn *rid_manager_dn,
					struct ldb_dn *ntds_dn, struct ldb_dn **dn,
					struct ldb_request *parent)
{
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
	int ret;
	struct ldb_message *msg;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	static const struct ridalloc_ridset_values o = {
		.alloc_pool	= UINT64_MAX,
		.prev_pool	= UINT64_MAX,
		.next_rid	= UINT32_MAX,
		.used_pool	= UINT32_MAX,
	};
	struct ridalloc_ridset_values n = {
		.alloc_pool	= 0,
		.prev_pool	= 0,
		.next_rid	= 0,
		.used_pool	= 0,
	};

	/*
	  steps:

	  find the machine object for the DC
	  construct the RID Set DN
	  load rIDAvailablePool to find next available set
	  modify RID Manager object to update rIDAvailablePool
	  add the RID Set object
	  link to the RID Set object in machine object
	 */

	server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
	if (!server_dn) {
		talloc_free(tmp_ctx);
		return ldb_module_oom(module);
	}

	ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
				       ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
	if (rid_set_dn == NULL) {
		talloc_free(tmp_ctx);
		return ldb_module_oom(module);
	}

	if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
		talloc_free(tmp_ctx);
		return ldb_module_oom(module);
	}

	/* grab a pool from the RID Manager object */
	ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool, parent);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	/* create the RID Set object */
	msg = ldb_msg_new(tmp_ctx);
	msg->dn = rid_set_dn;

	ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = ridalloc_set_ridset_values(module, msg, &o, &n);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	/* we need this to go all the way to the top of the module
	 * stack, as we need all the extra attributes added (including
	 * complex ones like ntsecuritydescriptor) */
	ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
				       ldb_dn_get_linearized(msg->dn),
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	/* add the rIDSetReferences link */
	msg = ldb_msg_new(tmp_ctx);
	msg->dn = machine_dn;

	ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn));
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}
	msg->elements[0].flags = LDB_FLAG_MOD_ADD;

	ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
				       ldb_dn_get_linearized(msg->dn),
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	(*dn) = talloc_steal(mem_ctx, rid_set_dn);

	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}


/*
  create a RID Set object for this DC
 */
static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
				       struct ldb_dn **dn, struct ldb_request *parent)
{
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);

	/* work out who is the RID Manager */
	ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	/* find the DN of the RID Manager */
	ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
		ridalloc_poke_rid_manager(module);
		ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn, parent);
	talloc_free(tmp_ctx);
	return ret;
}
Beispiel #13
0
/* 
   test offline file handling
*/
bool torture_test_offline(struct torture_context *torture)
{
	bool ret = true;
	TALLOC_CTX *mem_ctx = talloc_new(torture);
	int i;
	int timelimit = torture_setting_int(torture, "timelimit", 10);
	struct timeval tv;
	struct offline_state *state;
	struct smbcli_state *cli;
	bool progress;
	progress = torture_setting_bool(torture, "progress", true);

	nconnections = torture_setting_int(torture, "nprocs", 4);
	numstates = nconnections * torture_entries;

	state = talloc_zero_array(mem_ctx, struct offline_state, numstates);

	printf("Opening %d connections with %d simultaneous operations and %u files\n", nconnections, numstates, torture_numops);
	for (i=0;i<nconnections;i++) {
		state[i].tctx = torture;
		state[i].mem_ctx = talloc_new(state);
		state[i].ev = torture->ev;
		if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) {
			return false;
		}
		state[i].tree = cli->tree;
		state[i].client = i;
		/* allow more time for offline files */
		state[i].tree->session->transport->options.request_timeout = 200;
	}

	/* the others are repeats on the earlier connections */
	for (i=nconnections;i<numstates;i++) {
		state[i].tctx = torture;
		state[i].mem_ctx = talloc_new(state);
		state[i].ev = torture->ev;
		state[i].tree = state[i % nconnections].tree;
		state[i].client = i;
	}

	num_connected = i;

	if (!torture_setup_dir(cli, BASEDIR)) {
		goto failed;
	}

	/* pre-create files */
	printf("Pre-creating %u files ....\n", torture_numops);
	for (i=0;i<torture_numops;i++) {
		int fnum;
		char *fname = filename(mem_ctx, i);
		char buf[FILE_SIZE];
		NTSTATUS status;

		memset(buf, 1+(i % 255), sizeof(buf));

		fnum = smbcli_open(state[0].tree, fname, O_RDWR|O_CREAT, DENY_NONE);
		if (fnum == -1) {
			printf("Failed to open %s on connection %d\n", fname, i);
			goto failed;
		}

		if (smbcli_write(state[0].tree, fnum, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
			printf("Failed to write file of size %u\n", FILE_SIZE);
			goto failed;
		}

		status = smbcli_close(state[0].tree, fnum);
		if (!NT_STATUS_IS_OK(status)) {
			printf("Close failed - %s\n", nt_errstr(status));
			goto failed;
		}

		talloc_free(fname);
	}

	/* start the async ops */
	for (i=0;i<numstates;i++) {
		state[i].tv_start = timeval_current();
		test_offline(&state[i]);
	}

	tv = timeval_current();	

	if (progress) {
		event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state);
	}

	printf("Running for %d seconds\n", timelimit);
	while (timeval_elapsed(&tv) < timelimit) {
		event_loop_once(torture->ev);

		if (test_failed) {
			DEBUG(0,("test failed\n"));
			goto failed;
		}
	}

	printf("\nWaiting for completion\n");
	test_finished = true;
	for (i=0;i<numstates;i++) {
		while (state[i].loadfile || 
		       state[i].savefile ||
		       state[i].req) {
			event_loop_once(torture->ev);
		}
	}	

	printf("worst latencies: set_lat=%.1f get_lat=%.1f save_lat=%.1f load_lat=%.1f\n",
	       worst_latencies[OP_SETOFFLINE],
	       worst_latencies[OP_GETOFFLINE],
	       worst_latencies[OP_SAVEFILE],
	       worst_latencies[OP_LOADFILE]);

	smbcli_deltree(state[0].tree, BASEDIR);
	talloc_free(mem_ctx);
	printf("\n");
	return ret;

failed:
	talloc_free(mem_ctx);
	return false;
}
Beispiel #14
0
errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
                               struct confdb_ctx *cdb,
                               struct resp_ctx *rctx)
{
    errno_t ret;
    bool filter_set = false;
    char **filter_list = NULL;
    char *name = NULL;
    struct sss_domain_info *dom = NULL;
    struct sss_domain_info *domain_list = rctx->domains;
    char *domainname = NULL;
    char *conf_path = NULL;
    TALLOC_CTX *tmpctx = talloc_new(NULL);
    int i;

    /* Populate domain-specific negative cache entries */
    for (dom = domain_list; dom; dom = get_next_domain(dom, false)) {
        conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL,
                                    dom->name);
        if (!conf_path) {
            ret = ENOMEM;
            goto done;
        }

        talloc_zfree(filter_list);
        ret = confdb_get_string_as_list(cdb, tmpctx, conf_path,
                                        CONFDB_NSS_FILTER_USERS,
                                        &filter_list);
        if (ret == ENOENT) continue;
        if (ret != EOK) goto done;
        filter_set = true;

        for (i = 0; (filter_list && filter_list[i]); i++) {
            ret = sss_parse_name_for_domains(tmpctx, domain_list,
                                             rctx->default_domain,
                                             filter_list[i],
                                             &domainname, &name);
            if (ret != EOK) {
                DEBUG(1, ("Invalid name in filterUsers list: [%s] (%d)\n",
                         filter_list[i], ret));
                continue;
            }

            if (domainname && strcmp(domainname, dom->name)) {
                DEBUG(1, ("Mismatch between domain name (%s) and name "
                          "set in FQN  (%s), skipping user %s\n",
                          dom->name, domainname, name));
                continue;
            }

            ret = sss_ncache_set_user(ncache, true, dom, name);
            if (ret != EOK) {
                DEBUG(1, ("Failed to store permanent user filter for [%s]"
                          " (%d [%s])\n", filter_list[i],
                          ret, strerror(ret)));
                continue;
            }
        }
    }

    ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
                                    CONFDB_NSS_FILTER_USERS, &filter_list);
    if (ret == ENOENT) {
        if (!filter_set) {
            filter_list = talloc_array(tmpctx, char *, 2);
            if (!filter_list) {
                ret = ENOMEM;
                goto done;
            }
            filter_list[0] = talloc_strdup(tmpctx, "root");
            if (!filter_list[0]) {
                ret = ENOMEM;
                goto done;
            }
            filter_list[1] = NULL;
        }
    }
static int ldb_eval_transitive_filter_helper(TALLOC_CTX *mem_ctx,
					     struct ldb_context *ldb,
					     const char *attr,
					     const struct dsdb_dn *dn_to_match,
					     const char *dn_oid,
					     struct dsdb_dn *to_visit,
					     struct dsdb_dn ***visited,
					     unsigned int *visited_count,
					     bool *matched)
{
	TALLOC_CTX *tmp_ctx;
	int ret, i, j;
	struct ldb_result *res;
	struct ldb_message *msg;
	struct ldb_message_element *el;
	const char *attrs[] = { attr, NULL };

	tmp_ctx = talloc_new(mem_ctx);
	if (tmp_ctx == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/*
	 * Fetch the entry to_visit
	 *
	 * NOTE: This is a new LDB search from the TOP of the module
	 * stack.  This means that this search runs the whole stack
	 * from top to bottom.
	 *
	 * This may seem to be in-efficient, but it is also the only
	 * way to ensure that the ACLs for this search are applied
	 * correctly.
	 *
	 * Note also that we don't have the original request
	 * here, so we can not apply controls or timeouts here.
	 */
	ret = dsdb_search_dn(ldb, tmp_ctx, &res, to_visit->dn, attrs, 0);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}
	if (res->count != 1) {
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	msg = res->msgs[0];

	/* Fetch the attribute to match from the entry being visited */
	el = ldb_msg_find_element(msg, attr);
	if (el == NULL) {
		/* This entry does not have the attribute to match */
		talloc_free(tmp_ctx);
		*matched = false;
		return LDB_SUCCESS;
	}

	/*
	 * If the value to match is present in the attribute values of the
	 * current entry being visited, set matched to true and return OK
	 */
	for (i=0; i<el->num_values; i++) {
		struct dsdb_dn *dn;
		dn = dsdb_dn_parse(tmp_ctx, ldb, &el->values[i], dn_oid);
		if (dn == NULL) {
			talloc_free(tmp_ctx);
			*matched = false;
			return LDB_ERR_INVALID_DN_SYNTAX;
		}

		if (ldb_dn_compare(dn_to_match->dn, dn->dn) == 0) {
			talloc_free(tmp_ctx);
			*matched = true;
			return LDB_SUCCESS;
		}
	}

	/*
	 * If arrived here, the value to match is not in the values of the
	 * entry being visited. Add the entry being visited (to_visit)
	 * to the visited array. The array is (re)allocated in the parent
	 * memory context.
	 */
	if (visited == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	} else if (*visited == NULL) {
		*visited = talloc_array(mem_ctx, struct dsdb_dn *, 1);
		if (*visited == NULL) {
			talloc_free(tmp_ctx);
			return LDB_ERR_OPERATIONS_ERROR;
		}
		(*visited)[0] = to_visit;
		(*visited_count) = 1;
	} else {
Beispiel #16
0
/**
 * Commits a list of replicated objects.
 *
 * @param working_schema dsdb_schema to be used for resolving
 * 			 Classes/Attributes during Schema replication. If not NULL,
 * 			 it will be set on ldb and used while committing replicated objects
 */
WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
				      struct dsdb_schema *working_schema,
				      struct dsdb_extended_replicated_objects *objects,
				      uint64_t *notify_uSN)
{
	WERROR werr;
	struct ldb_result *ext_res;
	struct dsdb_schema *cur_schema = NULL;
	struct dsdb_schema *new_schema = NULL;
	int ret;
	uint64_t seq_num1, seq_num2;
	bool used_global_schema = false;

	TALLOC_CTX *tmp_ctx = talloc_new(objects);
	if (!tmp_ctx) {
		DEBUG(0,("Failed to start talloc\n"));
		return WERR_NOMEM;
	}

	/* TODO: handle linked attributes */

	/* wrap the extended operation in a transaction 
	   See [MS-DRSR] 3.3.2 Transactions
	 */
	ret = ldb_transaction_start(ldb);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ " Failed to start transaction\n"));
		return WERR_FOOBAR;
	}

	ret = dsdb_load_partition_usn(ldb, objects->partition_dn, &seq_num1, NULL);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ " Failed to load partition uSN\n"));
		ldb_transaction_cancel(ldb);
		TALLOC_FREE(tmp_ctx);
		return WERR_FOOBAR;		
	}

	/*
	 * Set working_schema for ldb in case we are replicating from Schema NC.
	 * Schema won't be reloaded during Replicated Objects commit, as it is
	 * done in a transaction. So we need some way to search for newly
	 * added Classes and Attributes
	 */
	if (working_schema) {
		/* store current schema so we can fall back in case of failure */
		cur_schema = dsdb_get_schema(ldb, tmp_ctx);
		used_global_schema = dsdb_uses_global_schema(ldb);

		ret = dsdb_reference_schema(ldb, working_schema, false);
		if (ret != LDB_SUCCESS) {
			DEBUG(0,(__location__ "Failed to reference working schema - %s\n",
				 ldb_strerror(ret)));
			/* TODO: Map LDB Error to NTSTATUS? */
			ldb_transaction_cancel(ldb);
			TALLOC_FREE(tmp_ctx);
			return WERR_INTERNAL_ERROR;
		}
	}

	ret = ldb_extended(ldb, DSDB_EXTENDED_REPLICATED_OBJECTS_OID, objects, &ext_res);
	if (ret != LDB_SUCCESS) {
		/* restore previous schema */
		if (used_global_schema) { 
			dsdb_set_global_schema(ldb);
		} else if (cur_schema) {
			dsdb_reference_schema(ldb, cur_schema, false);
		}

		DEBUG(0,("Failed to apply records: %s: %s\n",
			 ldb_errstring(ldb), ldb_strerror(ret)));
		ldb_transaction_cancel(ldb);
		TALLOC_FREE(tmp_ctx);
		return WERR_FOOBAR;
	}
	talloc_free(ext_res);

	/* Save our updated prefixMap */
	if (working_schema) {
		werr = dsdb_write_prefixes_from_schema_to_ldb(working_schema,
							      ldb,
							      working_schema);
		if (!W_ERROR_IS_OK(werr)) {
			/* restore previous schema */
			if (used_global_schema) { 
				dsdb_set_global_schema(ldb);
			} else if (cur_schema ) {
				dsdb_reference_schema(ldb, cur_schema, false);
			}
			DEBUG(0,("Failed to save updated prefixMap: %s\n",
				 win_errstr(werr)));
			TALLOC_FREE(tmp_ctx);
			return werr;
		}
	}

	ret = ldb_transaction_prepare_commit(ldb);
	if (ret != LDB_SUCCESS) {
		/* restore previous schema */
		if (used_global_schema) { 
			dsdb_set_global_schema(ldb);
		} else if (cur_schema ) {
			dsdb_reference_schema(ldb, cur_schema, false);
		}
		DEBUG(0,(__location__ " Failed to prepare commit of transaction: %s\n",
			 ldb_errstring(ldb)));
		TALLOC_FREE(tmp_ctx);
		return WERR_FOOBAR;
	}

	ret = dsdb_load_partition_usn(ldb, objects->partition_dn, &seq_num2, NULL);
	if (ret != LDB_SUCCESS) {
		/* restore previous schema */
		if (used_global_schema) { 
			dsdb_set_global_schema(ldb);
		} else if (cur_schema ) {
			dsdb_reference_schema(ldb, cur_schema, false);
		}
		DEBUG(0,(__location__ " Failed to load partition uSN\n"));
		ldb_transaction_cancel(ldb);
		TALLOC_FREE(tmp_ctx);
		return WERR_FOOBAR;		
	}

	/* if this replication partner didn't need to be notified
	   before this transaction then it still doesn't need to be
	   notified, as the changes came from this server */	
	if (seq_num2 > seq_num1 && seq_num1 <= *notify_uSN) {
		*notify_uSN = seq_num2;
	}

	ret = ldb_transaction_commit(ldb);
	if (ret != LDB_SUCCESS) {
		/* restore previous schema */
		if (used_global_schema) { 
			dsdb_set_global_schema(ldb);
		} else if (cur_schema ) {
			dsdb_reference_schema(ldb, cur_schema, false);
		}
		DEBUG(0,(__location__ " Failed to commit transaction\n"));
		TALLOC_FREE(tmp_ctx);
		return WERR_FOOBAR;
	}

	/*
	 * Reset the Schema used by ldb. This will lead to
	 * a schema cache being refreshed from database.
	 */
	if (working_schema) {
		struct ldb_message *msg;
		struct ldb_request *req;

		/* Force a reload */
		working_schema->last_refresh = 0;
		new_schema = dsdb_get_schema(ldb, tmp_ctx);
		/* TODO: 
		 * If dsdb_get_schema() fails, we just fall back
		 * to what we had.  However, the database is probably
		 * unable to operate for other users from this
		 * point... */
		if (new_schema && used_global_schema) {
			dsdb_make_schema_global(ldb, new_schema);
		} else if (used_global_schema) { 
			DEBUG(0,("Failed to re-load schema after commit of transaction\n"));
			dsdb_set_global_schema(ldb);
			TALLOC_FREE(tmp_ctx);
			return WERR_INTERNAL_ERROR;
		} else {
			DEBUG(0,("Failed to re-load schema after commit of transaction\n"));
			dsdb_reference_schema(ldb, cur_schema, false);
			TALLOC_FREE(tmp_ctx);
			return WERR_INTERNAL_ERROR;
		}
		msg = ldb_msg_new(tmp_ctx);
		if (msg == NULL) {
			TALLOC_FREE(tmp_ctx);
			return WERR_NOMEM;
		}
		msg->dn = ldb_dn_new(msg, ldb, "");
		if (msg->dn == NULL) {
			TALLOC_FREE(tmp_ctx);
			return WERR_NOMEM;
		}

		ret = ldb_msg_add_string(msg, "schemaUpdateNow", "1");
		if (ret != LDB_SUCCESS) {
			TALLOC_FREE(tmp_ctx);
			return WERR_INTERNAL_ERROR;
		}

		ret = ldb_build_mod_req(&req, ldb, objects,
				msg,
				LDB_SCOPE_BASE,
				NULL,
				ldb_op_default_callback,
				NULL);

		if (ret != LDB_SUCCESS) {
			TALLOC_FREE(tmp_ctx);
			return WERR_DS_DRA_INTERNAL_ERROR;
		}

		ret = ldb_transaction_start(ldb);
		if (ret != LDB_SUCCESS) {
			TALLOC_FREE(tmp_ctx);
			DEBUG(0, ("Autotransaction start failed\n"));
			return WERR_DS_DRA_INTERNAL_ERROR;
		}

		ret = ldb_request(ldb, req);
		if (ret == LDB_SUCCESS) {
			ret = ldb_wait(req->handle, LDB_WAIT_ALL);
		}

		if (ret == LDB_SUCCESS) {
			ret = ldb_transaction_commit(ldb);
		} else {
			DEBUG(0, ("Schema update now failed: %s\n",
				  ldb_errstring(ldb)));
			ldb_transaction_cancel(ldb);
		}

		if (ret != LDB_SUCCESS) {
			DEBUG(0, ("Commit failed: %s\n", ldb_errstring(ldb)));
			TALLOC_FREE(tmp_ctx);
			return WERR_DS_INTERNAL_FAILURE;
		}
	}

	DEBUG(2,("Replicated %u objects (%u linked attributes) for %s\n",
		 objects->num_objects, objects->linked_attributes_count,
		 ldb_dn_get_linearized(objects->partition_dn)));
		 
	TALLOC_FREE(tmp_ctx);
	return WERR_OK;
}
Beispiel #17
0
/*
  check that the SPN update should be allowed as an override
  via sam_ctx_system

  This is only called if the client is not a domain controller or
  administrator
 */
static bool writespn_check_spn(struct drsuapi_bind_state *b_state,
			       struct dcesrv_call_state *dce_call,
			       struct ldb_dn *dn,
			       const char *spn)
{
	/*
	 * we only allow SPN updates if:
	 *
	 * 1) they are on the clients own account object
	 * 2) they are of the form SERVICE/dnshostname
	 */
	struct dom_sid *user_sid, *sid;
	TALLOC_CTX *tmp_ctx = talloc_new(dce_call);
	struct ldb_result *res;
	const char *attrs[] = { "objectSID", "dNSHostName", NULL };
	int ret;
	krb5_context krb_ctx;
	krb5_error_code kerr;
	krb5_principal principal;
	const krb5_data *component;
	const char *dns_name, *dnsHostName;

	/* The service principal name shouldn't be NULL */
	if (spn == NULL) {
		talloc_free(tmp_ctx);
		return false;
	}

	/*
	  get the objectSid of the DN that is being modified, and
	  check it matches the user_sid in their token
	 */

	ret = dsdb_search_dn(b_state->sam_ctx, tmp_ctx, &res, dn, attrs,
			     DSDB_SEARCH_ONE_ONLY);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return false;
	}

	user_sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
	sid = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid");
	if (sid == NULL) {
		talloc_free(tmp_ctx);
		return false;
	}

	dnsHostName = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName",
						  NULL);
	if (dnsHostName == NULL) {
		talloc_free(tmp_ctx);
		return false;
	}

	if (!dom_sid_equal(sid, user_sid)) {
		talloc_free(tmp_ctx);
		return false;
	}

	kerr = smb_krb5_init_context_basic(tmp_ctx,
					   dce_call->conn->dce_ctx->lp_ctx,
					   &krb_ctx);
	if (kerr != 0) {
		talloc_free(tmp_ctx);
		return false;
	}

	ret = krb5_parse_name_flags(krb_ctx, spn, KRB5_PRINCIPAL_PARSE_NO_REALM,
				    &principal);
	if (kerr != 0) {
		krb5_free_context(krb_ctx);
		talloc_free(tmp_ctx);
		return false;
	}

	if (krb5_princ_size(krb_ctx, principal) != 2) {
		krb5_free_principal(krb_ctx, principal);
		krb5_free_context(krb_ctx);
		talloc_free(tmp_ctx);
		return false;
	}

	component = krb5_princ_component(krb_ctx, principal, 1);
	dns_name = (const char *)component->data;

	if (strcasecmp(dns_name, dnsHostName) != 0) {
		krb5_free_principal(krb_ctx, principal);
		krb5_free_context(krb_ctx);
		talloc_free(tmp_ctx);
		return false;
	}

	/* its a simple update on their own account - allow it with
	 * permissions override */
	krb5_free_principal(krb_ctx, principal);
	krb5_free_context(krb_ctx);
	talloc_free(tmp_ctx);

	return true;
}
Beispiel #18
0
static int pdc_fsmo_init(struct ldb_module *module)
{
	struct ldb_context *ldb;
	TALLOC_CTX *mem_ctx;
	struct ldb_dn *pdc_dn;
	struct dsdb_pdc_fsmo *pdc_fsmo;
	struct ldb_result *pdc_res;
	int ret;
	static const char *pdc_attrs[] = {
		"fSMORoleOwner",
		NULL
	};

	ldb = ldb_module_get_ctx(module);

	mem_ctx = talloc_new(module);
	if (!mem_ctx) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	pdc_dn = samdb_base_dn(ldb);
	if (!pdc_dn) {
		ldb_debug(ldb, LDB_DEBUG_WARNING,
			  "pdc_fsmo_init: no domain dn present: (skip loading of domain details)\n");
		talloc_free(mem_ctx);
		return ldb_next_init(module);
	}

	pdc_fsmo = talloc_zero(mem_ctx, struct dsdb_pdc_fsmo);
	if (!pdc_fsmo) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ldb_module_set_private(module, pdc_fsmo);

	ret = dsdb_module_search_dn(module, mem_ctx, &pdc_res,
				    pdc_dn, 
				    pdc_attrs, 0);
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		ldb_debug(ldb, LDB_DEBUG_WARNING,
			  "pdc_fsmo_init: no domain object present: (skip loading of domain details)\n");
		talloc_free(mem_ctx);
		return ldb_next_init(module);
	} else if (ret != LDB_SUCCESS) {
		ldb_debug_set(ldb, LDB_DEBUG_FATAL,
			      "pdc_fsmo_init: failed to search the domain object: %d:%s",
			      ret, ldb_strerror(ret));
		talloc_free(mem_ctx);
		return ret;
	}

	pdc_fsmo->master_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, pdc_res->msgs[0], "fSMORoleOwner");
	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc_fsmo->master_dn) == 0) {
		pdc_fsmo->we_are_master = true;
	} else {
		pdc_fsmo->we_are_master = false;
	}

	if (ldb_set_opaque(ldb, "dsdb_pdc_fsmo", pdc_fsmo) != LDB_SUCCESS) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	talloc_steal(module, pdc_fsmo);

	ldb_debug(ldb, LDB_DEBUG_TRACE,
			  "pdc_fsmo_init: we are master: %s\n",
			  (pdc_fsmo->we_are_master?"yes":"no"));

	talloc_free(mem_ctx);
	return ldb_next_init(module);
}
static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, struct ldb_context *ldb_ctx, 
						      TALLOC_CTX *mem_ctx,
						      const char *alias_from,
						      char **alias_to)
{
	unsigned int i;
	int ret;
	struct ldb_result *res;
	struct ldb_message_element *spnmappings;
	TALLOC_CTX *tmp_ctx;
	struct ldb_dn *service_dn;
	char *service_dn_str;

	const char *directory_attrs[] = {
		"sPNMappings", 
		NULL
	};

	tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
	}

	service_dn = ldb_dn_new(tmp_ctx, ldb_ctx, "CN=Directory Service,CN=Windows NT,CN=Services");
	if ( ! ldb_dn_add_base(service_dn, ldb_get_config_basedn(ldb_ctx))) {
		return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
	}
	service_dn_str = ldb_dn_alloc_linearized(tmp_ctx, service_dn);
	if ( ! service_dn_str) {
		return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
	}

	ret = ldb_search(ldb_ctx, tmp_ctx, &res, service_dn, LDB_SCOPE_BASE,
			 directory_attrs, "(objectClass=nTDSService)");

	if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
		DEBUG(1, ("ldb_search: dn: %s not found: %s\n", service_dn_str, ldb_errstring(ldb_ctx)));
		return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
	} else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		DEBUG(1, ("ldb_search: dn: %s not found\n", service_dn_str));
		return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
	} else if (res->count != 1) {
		talloc_free(res);
		DEBUG(1, ("ldb_search: dn: %s not found\n", service_dn_str));
		return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
	}

	spnmappings = ldb_msg_find_element(res->msgs[0], "sPNMappings");
	if (!spnmappings || spnmappings->num_values == 0) {
		DEBUG(1, ("ldb_search: dn: %s no sPNMappings attribute\n", service_dn_str));
		talloc_free(tmp_ctx);
		return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
	}

	for (i = 0; i < spnmappings->num_values; i++) {
		char *mapping, *p, *str;
		mapping = talloc_strdup(tmp_ctx, 
					(const char *)spnmappings->values[i].data);
		if (!mapping) {
			DEBUG(1, ("LDB_lookup_spn_alias: ldb_search: dn: %s did not have an sPNMapping\n", service_dn_str));
			talloc_free(tmp_ctx);
			return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
		}

		/* C string manipulation sucks */

		p = strchr(mapping, '=');
		if (!p) {
			DEBUG(1, ("ldb_search: dn: %s sPNMapping malformed: %s\n", 
				  service_dn_str, mapping));
			talloc_free(tmp_ctx);
			return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
		}
		p[0] = '\0';
		p++;
		do {
			str = p;
			p = strchr(p, ',');
			if (p) {
				p[0] = '\0';
				p++;
			}
			if (strcasecmp(str, alias_from) == 0) {
				*alias_to = mapping;
				talloc_steal(mem_ctx, mapping);
				talloc_free(tmp_ctx);
				return DRSUAPI_DS_NAME_STATUS_OK;
			}
		} while (p);
	}
	DEBUG(4, ("LDB_lookup_spn_alias: no alias for service %s applicable\n", alias_from));
	talloc_free(tmp_ctx);
	return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
}
static NTSTATUS sldb_create(struct share_context *ctx, const char *name, struct share_info *info, int count)
{
	struct ldb_context *ldb;
	struct ldb_message *msg;
	TALLOC_CTX *tmp_ctx;
	NTSTATUS ret;
	int err, i, j;

	for (i = 0, j = 0; i < count && j != 0x03; i++) {
		if (strcasecmp(info[i].name, SHARE_TYPE) == 0) j |= 0x02;
		if (strcasecmp(info[i].name, SHARE_PATH) == 0) j |= 0x01;
		if (strcasecmp(info[i].name, SHARE_NAME) == 0) {
			if (strcasecmp(name, (char *)info[i].value) != 0) {
				return NT_STATUS_INVALID_PARAMETER;
			}
		}
	}
	if (!name || j != 0x03) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	
	tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	ldb = talloc_get_type(ctx->priv_data, struct ldb_context);

	msg = ldb_msg_new(tmp_ctx);
	if (!msg) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		ret = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* TODO: escape info->name */
	msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
	if (!msg->dn) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		ret = NT_STATUS_NO_MEMORY;
		goto done;
	}

	SHARE_ADD_STRING("objectClass", "top");
	SHARE_ADD_STRING("objectClass", "share");
	SHARE_ADD_STRING("cn", name);
	SHARE_ADD_STRING(SHARE_NAME, name);

	for (i = 0; i < count; i++) {
		if (strcasecmp(info[i].name, SHARE_NAME) == 0) continue;

		switch (info[i].type) {
		case SHARE_INFO_STRING:
			SHARE_ADD_STRING(info[i].name, (char *)info[i].value);
			break;
		case SHARE_INFO_INT:
			SHARE_ADD_INT(info[i].name, *((int *)info[i].value));
			break;
		case SHARE_INFO_BLOB:
			SHARE_ADD_BLOB(info[i].name, (DATA_BLOB *)info[i].value);
			break;
		default:
			DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name));
			ret = NT_STATUS_INVALID_PARAMETER;
			goto done;
		}
	}

	/* TODO: Security Descriptor */

	SHARE_ADD_STRING(SHARE_AVAILABLE, "true");
	SHARE_ADD_STRING(SHARE_BROWSEABLE, "true");
	SHARE_ADD_STRING(SHARE_READONLY, "false");
	SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "unixuid");
	SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "posix");

	err = ldb_add(ldb, msg);
	if (err != LDB_SUCCESS) {
		DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
			 "       err=%d [%s]\n", name, err, ldb_errstring(ldb)));
		if (err == LDB_ERR_NO_SUCH_OBJECT) {
			ret = NT_STATUS_OBJECT_NAME_NOT_FOUND;
		} else if (err == LDB_ERR_ENTRY_ALREADY_EXISTS) {
			ret = NT_STATUS_OBJECT_NAME_COLLISION;
		} else {
			ret = NT_STATUS_UNSUCCESSFUL;
		}
		goto done;
	}

	ret = NT_STATUS_OK;
done:
	talloc_free(tmp_ctx);
	return ret;
}
Beispiel #21
0
krb5_error_code smb_krb5_init_context(void *parent_ctx,
				      struct loadparm_context *lp_ctx,
				      struct smb_krb5_context **smb_krb5_context)
{
	krb5_error_code ret;
	TALLOC_CTX *tmp_ctx;
	krb5_context kctx;
#ifdef SAMBA4_USES_HEIMDAL
	krb5_log_facility *logf;
#endif

	initialize_krb5_error_table();

	tmp_ctx = talloc_new(parent_ctx);
	*smb_krb5_context = talloc_zero(tmp_ctx, struct smb_krb5_context);

	if (!*smb_krb5_context || !tmp_ctx) {
		talloc_free(tmp_ctx);
		return ENOMEM;
	}

	ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx, &kctx);
	if (ret) {
		DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n",
			 error_message(ret)));
		talloc_free(tmp_ctx);
		return ret;
	}
	(*smb_krb5_context)->krb5_context = kctx;

	talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy);

#ifdef SAMBA4_USES_HEIMDAL
	/* TODO: Should we have a different name here? */
	ret = krb5_initlog(kctx, "Samba", &logf);

	if (ret) {
		DEBUG(1,("krb5_initlog failed (%s)\n",
			 smb_get_krb5_error_message(kctx, ret, tmp_ctx)));
		talloc_free(tmp_ctx);
		return ret;
	}
	(*smb_krb5_context)->pvt_log_data = logf;

	ret = krb5_addlog_func(kctx, logf, 0 /* min */, -1 /* max */,
			       smb_krb5_debug_wrapper,
				smb_krb5_debug_close, NULL);
	if (ret) {
		DEBUG(1,("krb5_addlog_func failed (%s)\n",
			 smb_get_krb5_error_message(kctx, ret, tmp_ctx)));
		talloc_free(tmp_ctx);
		return ret;
	}
	krb5_set_warn_dest(kctx, logf);

	/* Set options in kerberos */

	krb5_set_dns_canonicalize_hostname(kctx,
			lpcfg_parm_bool(lp_ctx, NULL, "krb5",
					"set_dns_canonicalize", false));
#endif
	talloc_steal(parent_ctx, *smb_krb5_context);
	talloc_free(tmp_ctx);

	return 0;
}
static NTSTATUS sldb_set(struct share_context *ctx, const char *name, struct share_info *info, int count)
{
	struct ldb_context *ldb;
	struct ldb_message *msg;
	TALLOC_CTX *tmp_ctx;
	NTSTATUS ret;
	bool do_rename = false;
	char *newname;
	int err, i;

	if (!name) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	
	tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	ldb = talloc_get_type(ctx->priv_data, struct ldb_context);

	msg = ldb_msg_new(tmp_ctx);
	if (!msg) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		ret = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* TODO: escape name */
	msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
	if (!msg->dn) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		ret = NT_STATUS_NO_MEMORY;
		goto done;
	}

	for (i = 0; i < count; i++) {
		if (strcasecmp(info[i].name, SHARE_NAME) == 0) {
			if (strcasecmp(name, (char *)info[i].value) != 0) {
				do_rename = true;
				newname = (char *)info[i].value;
				SHARE_MOD_STRING("cn", (char *)info[i].value);
			}
		}

		switch (info[i].type) {
		case SHARE_INFO_STRING:
			SHARE_MOD_STRING(info[i].name, (char *)info[i].value);
			break;
		case SHARE_INFO_INT:
			SHARE_MOD_INT(info[i].name, *((int *)info[i].value));
			break;
		case SHARE_INFO_BLOB:
			SHARE_MOD_BLOB(info[i].name, (DATA_BLOB *)info[i].value);
			break;
		default:
			DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name));
			ret = NT_STATUS_INVALID_PARAMETER;
			goto done;
		}
	}

	if (do_rename) {
		struct ldb_dn *olddn, *newdn;

		olddn = msg->dn;

		/* TODO: escape newname */
		newdn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", newname);
		if (!newdn) {
			DEBUG(0,("ERROR: Out of memory!\n"));
			ret = NT_STATUS_NO_MEMORY;
			goto done;
		}

		err = ldb_rename(ldb, olddn, newdn);
		if (err != LDB_SUCCESS) {
			DEBUG(2,("ERROR: unable to rename share %s (to %s)\n"
				 "       err=%d [%s]\n", name, newname, err, ldb_errstring(ldb)));
			if (err == LDB_ERR_NO_SUCH_OBJECT) {
				ret = NT_STATUS_OBJECT_NAME_COLLISION;
			} else {
				ret = NT_STATUS_UNSUCCESSFUL;
			}
			goto done;
		}

		msg->dn = newdn;
	}

	err = ldb_modify(ldb, msg);
	if (err != LDB_SUCCESS) {
		DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
			 "       err=%d [%s]\n", name, err, ldb_errstring(ldb)));
		if (err == LDB_ERR_NO_SUCH_OBJECT) {
			ret = NT_STATUS_OBJECT_NAME_COLLISION;
		} else {
			ret = NT_STATUS_UNSUCCESSFUL;
		}
		goto done;
	}

	ret = NT_STATUS_OK;
done:
	talloc_free(tmp_ctx);
	return ret;
}
Beispiel #23
0
WERROR dreplsrv_load_partitions(struct dreplsrv_service *s)
{
	WERROR status;
	static const char *attrs[] = { "hasMasterNCs", "hasPartialReplicaNCs", NULL };
	unsigned int i;
	int ret;
	TALLOC_CTX *tmp_ctx;
	struct ldb_result *res;
	struct ldb_message_element *el;
	struct ldb_dn *ntds_dn;

	tmp_ctx = talloc_new(s);
	W_ERROR_HAVE_NO_MEMORY(tmp_ctx);

	ntds_dn = samdb_ntds_settings_dn(s->samdb);
	if (!ntds_dn) {
		DEBUG(1,(__location__ ": Unable to find ntds_dn: %s\n", ldb_errstring(s->samdb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, ntds_dn, attrs, DSDB_SEARCH_SHOW_EXTENDED_DN);
	if (ret != LDB_SUCCESS) {
		DEBUG(1,("Searching for hasMasterNCs in NTDS DN failed: %s\n", ldb_errstring(s->samdb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	el = ldb_msg_find_element(res->msgs[0], "hasMasterNCs");
	if (!el) {
		DEBUG(1,("Finding hasMasterNCs element in root_res failed: %s\n",
			 ldb_errstring(s->samdb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	for (i=0; i<el->num_values; i++) {
		struct ldb_dn *pdn;
		struct dreplsrv_partition *p;

		pdn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]);
		if (pdn == NULL) {
			talloc_free(tmp_ctx);
			return WERR_DS_DRA_INTERNAL_ERROR;
		}
		if (!ldb_dn_validate(pdn)) {
			return WERR_DS_DRA_INTERNAL_ERROR;
		}

		p = talloc_zero(s, struct dreplsrv_partition);
		W_ERROR_HAVE_NO_MEMORY(p);

		p->dn = talloc_steal(p, pdn);
		p->service = s;

		DLIST_ADD(s->partitions, p);

		DEBUG(2, ("dreplsrv_partition[%s] loaded\n", ldb_dn_get_linearized(p->dn)));
	}

	el = ldb_msg_find_element(res->msgs[0], "hasPartialReplicaNCs");

	for (i=0; el && i<el->num_values; i++) {
		struct ldb_dn *pdn;
		struct dreplsrv_partition *p;

		pdn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]);
		if (pdn == NULL) {
			talloc_free(tmp_ctx);
			return WERR_DS_DRA_INTERNAL_ERROR;
		}
		if (!ldb_dn_validate(pdn)) {
			return WERR_DS_DRA_INTERNAL_ERROR;
		}

		p = talloc_zero(s, struct dreplsrv_partition);
		W_ERROR_HAVE_NO_MEMORY(p);

		p->dn = talloc_steal(p, pdn);
		p->partial_replica = true;
		p->service = s;

		DLIST_ADD(s->partitions, p);

		DEBUG(2, ("dreplsrv_partition[%s] loaded (partial replica)\n", ldb_dn_get_linearized(p->dn)));
	}

	talloc_free(tmp_ctx);

	status = dreplsrv_refresh_partitions(s);
	W_ERROR_NOT_OK_RETURN(status);

	return WERR_OK;
}
Beispiel #24
0
errno_t simple_access_check(struct simple_ctx *ctx, const char *username,
                            bool *access_granted)
{
    int i, j;
    errno_t ret;
    TALLOC_CTX *tmp_ctx = NULL;
    const char *user_attrs[] = { SYSDB_MEMBEROF,
                                 SYSDB_GIDNUM,
                                 NULL };
    const char *group_attrs[] = { SYSDB_NAME,
                                  NULL };
    struct ldb_message *msg;
    struct ldb_message_element *el;
    char **groups;
    const char *primary_group;
    gid_t gid;
    bool matched;

    *access_granted = false;

    /* First, check whether the user is in the allowed users list */
    if (ctx->allow_users != NULL) {
        for(i = 0; ctx->allow_users[i] != NULL; i++) {
            if (strcmp(username, ctx->allow_users[i]) == 0) {
                DEBUG(9, ("User [%s] found in allow list, access granted.\n",
                      username));

                /* Do not return immediately on explicit allow
                 * We need to make sure none of the user's groups
                 * are denied.
                 */
                *access_granted = true;
            }
        }
    } else if (!ctx->allow_groups) {
        /* If neither allow rule is in place, we'll assume allowed
         * unless a deny rule disables us below.
         */
        *access_granted = true;
    }

    /* Next check whether this user has been specifically denied */
    if (ctx->deny_users != NULL) {
        for(i = 0; ctx->deny_users[i] != NULL; i++) {
            if (strcmp(username, ctx->deny_users[i]) == 0) {
                DEBUG(9, ("User [%s] found in deny list, access denied.\n",
                      username));

                /* Return immediately on explicit denial */
                *access_granted = false;
                return EOK;
            }
        }
    }

    if (!ctx->allow_groups && !ctx->deny_groups) {
        /* There are no group restrictions, so just return
         * here with whatever we've decided.
         */
        return EOK;
    }

    /* Now get a list of this user's groups and check those against the
     * simple_allow_groups list.
     */
    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) {
        ret = ENOMEM;
        goto done;
    }

    ret = sysdb_search_user_by_name(tmp_ctx, ctx->sysdb,
                                    username, user_attrs, &msg);
    if (ret != EOK) {
        DEBUG(1, ("Could not look up username [%s]: [%d][%s]\n",
                  username, ret, strerror(ret)));
        goto done;
    }

    /* Construct a list of the user's groups */
    el = ldb_msg_find_element(msg, SYSDB_MEMBEROF);
    if (el && el->num_values) {
        /* Get the groups from the memberOf entries
         * Allocate the array with room for both the NULL
         * terminator and the primary group
         */
        groups = talloc_array(tmp_ctx, char *, el->num_values + 2);
        if (!groups) {
            ret = ENOMEM;
            goto done;
        }

        for (j = 0; j < el->num_values; j++) {
            ret = sysdb_group_dn_name(
                    ctx->sysdb, tmp_ctx,
                    (char *)el->values[j].data,
                    &groups[j]);
            if (ret != EOK) {
                goto done;
            }
        }
    } else {
/****************************************************************************
 purge stale printers and reload from pre-populated pcap cache
**************************************************************************/
void reload_printers_full(struct tevent_context *ev,
			  struct messaging_context *msg_ctx)
{
	struct auth_serversupplied_info *session_info = NULL;
	int n_services;
	int pnum;
	int snum;
	const char *pname;
	const char *sname;
	NTSTATUS status;

	n_services = lp_numservices();
	pnum = lp_servicenumber(PRINTERS_NAME);

	status = make_session_info_system(talloc_new(NULL), &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(3, ("Could not create system session_info\n"));
		/* can't remove stale printers before we
		 * are fully initilized */
		return;
	}

	/*
	 * Add default config for printers added to smb.conf file and remove
	 * stale printers
	 */
	for (snum = 0; snum < n_services; snum++) {
		/* avoid removing PRINTERS_NAME */
		if (snum == pnum) {
			continue;
		}

		/* skip no-printer services */
		if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
			continue;
		}

		sname = lp_const_servicename(snum);
		pname = lp_printername(snum);

		/* check printer, but avoid removing non-autoloaded printers */
		if (lp_autoloaded(snum) && !pcap_printername_ok(pname)) {
			struct spoolss_PrinterInfo2 *pinfo2 = NULL;
			if (is_printer_published(session_info, session_info,
						 msg_ctx,
						 NULL,
						 lp_servicename(snum),
						 &pinfo2)) {
				nt_printer_publish(session_info,
						   session_info,
						   msg_ctx,
						   pinfo2,
						   DSPRINT_UNPUBLISH);
				TALLOC_FREE(pinfo2);
			}
			nt_printer_remove(session_info, session_info, msg_ctx,
					  pname);
		} else {
			DEBUG(8, ("Adding default registry entry for printer "
				  "[%s], if it doesn't exist.\n", sname));
			nt_printer_add(session_info, session_info, msg_ctx,
				       sname);
		}
	}

	/* finally, purge old snums */
	reload_printers(ev, msg_ctx);

	TALLOC_FREE(session_info);
}
Beispiel #26
0
void test_deskprofile_get_filename_path(void **state)
{
    TALLOC_CTX *tmp_ctx;
    errno_t ret;
    char *result = NULL;
    const char *results[24];

    /* All the results are based as:
     * user and hostgroup match the rules;
     * group and host don't match the rules;
     */

    /* 1 = user, group, host, hostgroup */
    results[0] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"USER"_"GROUP"_"HOST"_"HOSTGROUP"_"RULE_NAME"."EXTENSION;
    /*  2 = user, group, hostgroup, host */
    results[1] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"USER"_"GROUP"_"HOSTGROUP"_"HOST"_"RULE_NAME"."EXTENSION;
    /*  3 = user, host, group, hostgroup */
    results[2] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"USER"_"HOST"_"GROUP"_"HOSTGROUP"_"RULE_NAME"."EXTENSION;
    /*  4 = user, host, hostgroup, group */
    results[3] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"USER"_"HOST"_"HOSTGROUP"_"GROUP"_"RULE_NAME"."EXTENSION;
    /*  5 = user, hostgroup, group, host */
    results[4] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"USER"_"HOSTGROUP"_"GROUP"_"HOST"_"RULE_NAME"."EXTENSION;
    /*  6 = user, hostgroup, host, group */
    results[5] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"USER"_"HOSTGROUP"_"HOST"_"GROUP"_"RULE_NAME"."EXTENSION;
    /*  7 = group, user, host, hostgroup */
    results[6] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"GROUP"_"USER"_"HOST"_"HOSTGROUP"_"RULE_NAME"."EXTENSION;
    /*  8 = group, user, hostgroup, host */
    results[7] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"GROUP"_"USER"_"HOSTGROUP"_"HOST"_"RULE_NAME"."EXTENSION;
    /*  9 = group, host, user, hostgroup */
    results[8] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"GROUP"_"HOST"_"USER"_"HOSTGROUP"_"RULE_NAME"."EXTENSION;
    /* 10 = group, host, hostgroup, user */
    results[9] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"GROUP"_"HOST"_"HOSTGROUP"_"USER"_"RULE_NAME"."EXTENSION;
    /* 11 = group, hostgroup, user, host */
    results[10] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"GROUP"_"HOSTGROUP"_"USER"_"HOST"_"RULE_NAME"."EXTENSION;
    /* 12 = group, hostgroup, host, user */
    results[11] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"GROUP"_"HOSTGROUP"_"HOST"_"USER"_"RULE_NAME"."EXTENSION;
    /* 13 = host, user, group, hostgroup */
    results[12] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOST"_"USER"_"GROUP"_"HOSTGROUP"_"RULE_NAME"."EXTENSION;
    /* 14 = host, user, hostgroup, group */
    results[13] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOST"_"USER"_"HOSTGROUP"_"GROUP"_"RULE_NAME"."EXTENSION;
    /* 15 = host, group, user, hostgroup */
    results[14] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOST"_"GROUP"_"USER"_"HOSTGROUP"_"RULE_NAME"."EXTENSION;
    /* 16 = host, group, hostgroup, user */
    results[15] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOST"_"GROUP"_"HOSTGROUP"_"USER"_"RULE_NAME"."EXTENSION;
    /* 17 = host, hostgroup, user, group */
    results[16] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOST"_"HOSTGROUP"_"USER"_"GROUP"_"RULE_NAME"."EXTENSION;
    /* 18 = host, hostgroup, group, user */
    results[17] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOST"_"HOSTGROUP"_"GROUP"_"USER"_"RULE_NAME"."EXTENSION;
    /* 19 = hostgroup, user, group, host */
    results[18] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOSTGROUP"_"USER"_"GROUP"_"HOST"_"RULE_NAME"."EXTENSION;
    /* 20 = hostgroup, user, host, group */
    results[19] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOSTGROUP"_"USER"_"HOST"_"GROUP"_"RULE_NAME"."EXTENSION;
    /* 21 = hostgroup, group, user, host */
    results[20] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOSTGROUP"_"GROUP"_"USER"_"HOST"_"RULE_NAME"."EXTENSION;
    /* 22 = hostgroup, group, host, user */
    results[21] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOSTGROUP"_"GROUP"_"HOST"_"USER"_"RULE_NAME"."EXTENSION;
    /* 23 = hostgroup, host, user, group */
    results[22] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOSTGROUP"_"HOST"_"USER"_"GROUP"_"RULE_NAME"."EXTENSION;
    /* 24 = hostgroup, host, group, user */
    results[23] = RULES_DIR"/"DOMAIN"/"USERNAME"/"PRIO"_"HOSTGROUP"_"HOST"_"GROUP"_"USER"_"RULE_NAME"."EXTENSION;

    tmp_ctx = talloc_new(NULL);
    assert_non_null(tmp_ctx);

    for (uint16_t i = 0; i < 24; i++) {
        ret = ipa_deskprofile_get_filename_path(tmp_ctx,
                                                i + 1,
                                                RULES_DIR,
                                                DOMAIN,
                                                USERNAME,
                                                PRIO,
                                                USER,
                                                GROUP,
                                                HOST,
                                                HOSTGROUP,
                                                RULE_NAME,
                                                EXTENSION,
                                                &result);
        assert_int_equal(ret, EOK);
        assert_string_equal(results[i], result);

        talloc_zfree(result);
    }

    talloc_free(tmp_ctx);
}
Beispiel #27
0
/* issue refresh of specific sudo rules */
static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
                                                       struct sdap_sudo_ctx *sudo_ctx,
                                                       struct be_ctx *be_ctx,
                                                       struct sdap_options *opts,
                                                       struct sdap_id_conn_cache *conn_cache,
                                                       char **rules)
{
    struct tevent_req *req = NULL;
    struct tevent_req *subreq = NULL;
    struct sdap_sudo_rules_refresh_state *state = NULL;
    TALLOC_CTX *tmp_ctx = NULL;
    char *ldap_filter = NULL;
    char *ldap_full_filter = NULL;
    char *sysdb_filter = NULL;
    char *safe_rule = NULL;
    int ret;
    int i;

    if (rules == NULL) {
        return NULL;
    }

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
        return NULL;
    }

    req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_rules_refresh_state);
    if (req == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
        return NULL;
    }

    ldap_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
    sysdb_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */

    /* Download only selected rules from LDAP */
    /* Remove all selected rules from cache */
    for (i = 0; rules[i] != NULL; i++) {
        ret = sss_filter_sanitize(tmp_ctx, rules[i], &safe_rule);
        if (ret != EOK) {
            ret = ENOMEM;
            goto immediately;
        }

        ldap_filter = talloc_asprintf_append_buffer(ldap_filter, "(%s=%s)",
                                     opts->sudorule_map[SDAP_AT_SUDO_NAME].name,
                                     safe_rule);
        if (ldap_filter == NULL) {
            ret = ENOMEM;
            goto immediately;
        }

        sysdb_filter = talloc_asprintf_append_buffer(sysdb_filter, "(%s=%s)",
                                                     SYSDB_SUDO_CACHE_AT_CN,
                                                     safe_rule);
        if (sysdb_filter == NULL) {
            ret = ENOMEM;
            goto immediately;
        }
    }

    state->id_ctx = sudo_ctx->id_ctx;
    state->num_rules = i;

    ldap_filter = talloc_asprintf(tmp_ctx, "(&"SDAP_SUDO_FILTER_CLASS"(|%s))",
                                  opts->sudorule_map[SDAP_OC_SUDORULE].name,
                                  ldap_filter);
    if (ldap_filter == NULL) {
        ret = ENOMEM;
        goto immediately;
    }

    ldap_full_filter = sdap_sudo_get_filter(tmp_ctx, opts->sudorule_map,
                                            sudo_ctx, ldap_filter);
    if (ldap_full_filter == NULL) {
        ret = ENOMEM;
        goto immediately;
    }

    sysdb_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(|%s))",
                                   SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC,
                                   sysdb_filter);
    if (sysdb_filter == NULL) {
        ret = ENOMEM;
        goto immediately;
    }

    subreq = sdap_sudo_refresh_send(req, be_ctx, opts, conn_cache,
                                    ldap_full_filter, sysdb_filter);
    if (subreq == NULL) {
        ret = ENOMEM;
        goto immediately;
    }

    tevent_req_set_callback(subreq, sdap_sudo_rules_refresh_done, req);

    ret = EOK;
immediately:
    talloc_free(tmp_ctx);

    if (ret != EOK) {
        tevent_req_error(req, ret);
        tevent_req_post(req, be_ctx->ev);
    }

    return req;
}
Beispiel #28
0
/**
* @brief Decode a blob containing a NDR envoded PAC structure
*
* @param mem_ctx	  - The memory context
* @param pac_data_blob	  - The data blob containing the NDR encoded data
* @param context	  - The Kerberos Context
* @param service_keyblock - The Service Key used to verify the checksum
* @param client_principal - The client principal
* @param tgs_authtime     - The ticket timestamp
* @param pac_data_out	  - [out] The decoded PAC
*
* @return - A NTSTATUS error code
*/
NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
			     DATA_BLOB pac_data_blob,
			     krb5_context context,
			     const krb5_keyblock *krbtgt_keyblock,
			     const krb5_keyblock *service_keyblock,
			     krb5_const_principal client_principal,
			     time_t tgs_authtime,
			     struct PAC_DATA **pac_data_out)
{
	NTSTATUS status;
	enum ndr_err_code ndr_err;
	krb5_error_code ret;
	DATA_BLOB modified_pac_blob;

	NTTIME tgs_authtime_nttime;
	krb5_principal client_principal_pac = NULL;
	int i;

	struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
	struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
	struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
	struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
	struct PAC_LOGON_NAME *logon_name = NULL;
	struct PAC_LOGON_INFO *logon_info = NULL;
	struct PAC_DATA *pac_data = NULL;
	struct PAC_DATA_RAW *pac_data_raw = NULL;

	DATA_BLOB *srv_sig_blob = NULL;
	DATA_BLOB *kdc_sig_blob = NULL;

	bool bool_ret;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	if (pac_data_out) {
		*pac_data_out = NULL;
	}

	pac_data = talloc(tmp_ctx, struct PAC_DATA);
	pac_data_raw = talloc(tmp_ctx, struct PAC_DATA_RAW);
	kdc_sig_wipe = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA);
	srv_sig_wipe = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA);
	if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	ndr_err = ndr_pull_struct_blob(&pac_data_blob, pac_data, pac_data,
		       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC: %s\n",
			nt_errstr(status)));
		talloc_free(tmp_ctx);
		return status;
	}

	if (pac_data->num_buffers < 4) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0,("less than 4 PAC buffers\n"));
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	ndr_err = ndr_pull_struct_blob(
				&pac_data_blob, pac_data_raw, pac_data_raw,
				(ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC: %s\n",
			nt_errstr(status)));
		talloc_free(tmp_ctx);
		return status;
	}

	if (pac_data_raw->num_buffers < 4) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0,("less than 4 PAC buffers\n"));
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (pac_data->num_buffers != pac_data_raw->num_buffers) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0, ("misparse! PAC_DATA has %d buffers while "
			  "PAC_DATA_RAW has %d\n", pac_data->num_buffers,
			  pac_data_raw->num_buffers));
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	for (i=0; i < pac_data->num_buffers; i++) {
		struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
		struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i];

		if (data_buf->type != raw_buf->type) {
			DEBUG(0, ("misparse! PAC_DATA buffer %d has type "
				  "%d while PAC_DATA_RAW has %d\n", i,
				  data_buf->type, raw_buf->type));
			talloc_free(tmp_ctx);
			return NT_STATUS_INVALID_PARAMETER;
		}
		switch (data_buf->type) {
		case PAC_TYPE_LOGON_INFO:
			if (!data_buf->info) {
				break;
			}
			logon_info = data_buf->info->logon_info.info;
			break;
		case PAC_TYPE_SRV_CHECKSUM:
			if (!data_buf->info) {
				break;
			}
			srv_sig_ptr = &data_buf->info->srv_cksum;
			srv_sig_blob = &raw_buf->info->remaining;
			break;
		case PAC_TYPE_KDC_CHECKSUM:
			if (!data_buf->info) {
				break;
			}
			kdc_sig_ptr = &data_buf->info->kdc_cksum;
			kdc_sig_blob = &raw_buf->info->remaining;
			break;
		case PAC_TYPE_LOGON_NAME:
			logon_name = &data_buf->info->logon_name;
			break;
		default:
			break;
		}
	}

	if (!logon_info) {
		DEBUG(0,("PAC no logon_info\n"));
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!logon_name) {
		DEBUG(0,("PAC no logon_name\n"));
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!srv_sig_ptr || !srv_sig_blob) {
		DEBUG(0,("PAC no srv_key\n"));
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!kdc_sig_ptr || !kdc_sig_blob) {
		DEBUG(0,("PAC no kdc_key\n"));
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* Find and zero out the signatures,
	 * as required by the signing algorithm */

	/* We find the data blobs above,
	 * now we parse them to get at the exact portion we should zero */
	ndr_err = ndr_pull_struct_blob(
			kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe,
			(ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the KDC signature: %s\n",
			nt_errstr(status)));
		talloc_free(tmp_ctx);
		return status;
	}

	ndr_err = ndr_pull_struct_blob(
			srv_sig_blob, srv_sig_wipe, srv_sig_wipe,
			(ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the SRV signature: %s\n",
			nt_errstr(status)));
		talloc_free(tmp_ctx);
		return status;
	}

	/* Now zero the decoded structure */
	memset(kdc_sig_wipe->signature.data,
		'\0', kdc_sig_wipe->signature.length);
	memset(srv_sig_wipe->signature.data,
		'\0', srv_sig_wipe->signature.length);

	/* and reencode, back into the same place it came from */
	ndr_err = ndr_push_struct_blob(
			kdc_sig_blob, pac_data_raw, kdc_sig_wipe,
			(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the KDC signature: %s\n",
			nt_errstr(status)));
		talloc_free(tmp_ctx);
		return status;
	}
	ndr_err = ndr_push_struct_blob(
			srv_sig_blob, pac_data_raw, srv_sig_wipe,
			(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the SRV signature: %s\n",
			nt_errstr(status)));
		talloc_free(tmp_ctx);
		return status;
	}

	/* push out the whole structure, but now with zero'ed signatures */
	ndr_err = ndr_push_struct_blob(
			&modified_pac_blob, pac_data_raw, pac_data_raw,
			(ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the RAW PAC: %s\n",
			nt_errstr(status)));
		talloc_free(tmp_ctx);
		return status;
	}

	if (service_keyblock) {
		/* verify by service_key */
		ret = check_pac_checksum(modified_pac_blob, srv_sig_ptr,
					 context,
					 service_keyblock);
		if (ret) {
			DEBUG(5, ("PAC Decode: Failed to verify the service "
				  "signature: %s\n", error_message(ret)));
			return NT_STATUS_ACCESS_DENIED;
		}

		if (krbtgt_keyblock) {
			/* verify the service key checksum by krbtgt_key */
			ret = check_pac_checksum(srv_sig_ptr->signature, kdc_sig_ptr,
						 context, krbtgt_keyblock);
			if (ret) {
				DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
					  smb_get_krb5_error_message(context, ret, tmp_ctx)));
				talloc_free(tmp_ctx);
				return NT_STATUS_ACCESS_DENIED;
			}
		}
	}

	if (tgs_authtime) {
		/* Convert to NT time, so as not to loose accuracy in comparison */
		unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);

		if (tgs_authtime_nttime != logon_name->logon_time) {
			DEBUG(2, ("PAC Decode: "
				  "Logon time mismatch between ticket and PAC!\n"));
			DEBUG(2, ("PAC Decode: PAC: %s\n",
				  nt_time_string(tmp_ctx, logon_name->logon_time)));
			DEBUG(2, ("PAC Decode: Ticket: %s\n",
				  nt_time_string(tmp_ctx, tgs_authtime_nttime)));
			talloc_free(tmp_ctx);
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	if (client_principal) {
		ret = smb_krb5_parse_name_norealm(context,
						  logon_name->account_name,
						  &client_principal_pac);
		if (ret) {
			DEBUG(2, ("Could not parse name from PAC: [%s]:%s\n",
				  logon_name->account_name, error_message(ret)));
			talloc_free(tmp_ctx);
			return NT_STATUS_INVALID_PARAMETER;
		}

		bool_ret = smb_krb5_principal_compare_any_realm(context,
								client_principal,
								client_principal_pac);

		krb5_free_principal(context, client_principal_pac);

		if (!bool_ret) {
			DEBUG(2, ("Name in PAC [%s] does not match principal name "
				  "in ticket\n", logon_name->account_name));
			talloc_free(tmp_ctx);
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	DEBUG(3,("Found account name from PAC: %s [%s]\n",
		 logon_info->info3.base.account_name.string,
		 logon_info->info3.base.full_name.string));

	DEBUG(10,("Successfully validated Kerberos PAC\n"));

	if (DEBUGLEVEL >= 10) {
		const char *s;
		s = NDR_PRINT_STRUCT_STRING(tmp_ctx, PAC_DATA, pac_data);
		if (s) {
			DEBUGADD(10,("%s\n", s));
		}
	}

	if (pac_data_out) {
		*pac_data_out = talloc_steal(mem_ctx, pac_data);
	}

	return NT_STATUS_OK;
}
/*
  construct the token groups for SAM objects from a message
*/
static int construct_generic_token_groups(struct ldb_module *module,
					  struct ldb_message *msg, enum ldb_scope scope,
					  struct ldb_request *parent,
					  const char *attribute_string,
					  enum search_type type)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	TALLOC_CTX *tmp_ctx = talloc_new(msg);
	unsigned int i;
	int ret;
	const char *filter;

	NTSTATUS status;

	struct dom_sid *primary_group_sid;
	const char *primary_group_string;
	const char *primary_group_dn;
	DATA_BLOB primary_group_blob;

	struct dom_sid *account_sid;
	const char *account_sid_string;
	const char *account_sid_dn;
	DATA_BLOB account_sid_blob;
	struct dom_sid *groupSIDs = NULL;
	unsigned int num_groupSIDs = 0;

	struct dom_sid *domain_sid;

	if (scope != LDB_SCOPE_BASE) {
		ldb_set_errstring(ldb, "Cannot provide tokenGroups attribute, this is not a BASE search");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* If it's not a user, it won't have a primaryGroupID */
	if (ldb_msg_find_element(msg, "primaryGroupID") == NULL) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	/* Ensure it has an objectSID too */
	account_sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
	if (account_sid == NULL) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	status = dom_sid_split_rid(tmp_ctx, account_sid, &domain_sid, NULL);
	if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
		talloc_free(tmp_ctx);
		return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
	} else if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	primary_group_sid = dom_sid_add_rid(tmp_ctx,
					    domain_sid,
					    ldb_msg_find_attr_as_uint(msg, "primaryGroupID", ~0));
	if (!primary_group_sid) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	/* only return security groups */
	switch(type) {
	case TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL:
		filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u)(|(groupType:1.2.840.113556.1.4.803:=%u)(groupType:1.2.840.113556.1.4.803:=%u)))",
					 GROUP_TYPE_SECURITY_ENABLED, GROUP_TYPE_ACCOUNT_GROUP, GROUP_TYPE_UNIVERSAL_GROUP);
		break;
	case TOKEN_GROUPS_NO_GC_ACCEPTABLE:
	case TOKEN_GROUPS:
		filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
					 GROUP_TYPE_SECURITY_ENABLED);
		break;
	}

	if (!filter) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	primary_group_string = dom_sid_string(tmp_ctx, primary_group_sid);
	if (!primary_group_string) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	primary_group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", primary_group_string);
	if (!primary_group_dn) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	primary_group_blob = data_blob_string_const(primary_group_dn);

	account_sid_string = dom_sid_string(tmp_ctx, account_sid);
	if (!account_sid_string) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	account_sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", account_sid_string);
	if (!account_sid_dn) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	account_sid_blob = data_blob_string_const(account_sid_dn);

	status = dsdb_expand_nested_groups(ldb, &account_sid_blob,
					   true, /* We don't want to add the object's SID itself,
						    it's not returend in this attribute */
					   filter,
					   tmp_ctx, &groupSIDs, &num_groupSIDs);

	if (!NT_STATUS_IS_OK(status)) {
		ldb_asprintf_errstring(ldb, "Failed to construct tokenGroups: expanding groups of SID %s failed: %s",
				       account_sid_string, nt_errstr(status));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* Expands the primary group - this function takes in
	 * memberOf-like values, so we fake one up with the
	 * <SID=S-...> format of DN and then let it expand
	 * them, as long as they meet the filter - so only
	 * domain groups, not builtin groups
	 */
	status = dsdb_expand_nested_groups(ldb, &primary_group_blob, false, filter,
					   tmp_ctx, &groupSIDs, &num_groupSIDs);
	if (!NT_STATUS_IS_OK(status)) {
		ldb_asprintf_errstring(ldb, "Failed to construct tokenGroups: expanding groups of SID %s failed: %s",
				       account_sid_string, nt_errstr(status));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	for (i=0; i < num_groupSIDs; i++) {
		ret = samdb_msg_add_dom_sid(ldb, msg, msg, attribute_string, &groupSIDs[i]);
		if (ret) {
			talloc_free(tmp_ctx);
			return ret;
		}
	}

	return LDB_SUCCESS;
}
Beispiel #30
0
static int local_db_delete(TALLOC_CTX *mem_ctx,
                           struct local_context *lctx,
                           const char *req_path)
{
    TALLOC_CTX *tmp_ctx;
    struct ldb_dn *dn;
    static const char *attrs[] = { NULL };
    struct ldb_result *res;
    int ret;

    DEBUG(SSSDBG_TRACE_FUNC, "Removing a secret from [%s]\n", req_path);

    tmp_ctx = talloc_new(mem_ctx);
    if (!tmp_ctx) return ENOMEM;

    ret = local_db_dn(mem_ctx, lctx->ldb, req_path, &dn);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE,
              "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
        goto done;
    }

    DEBUG(SSSDBG_TRACE_INTERNAL,
          "Searching for [%s] at [%s] with scope=base\n",
          LOCAL_CONTAINER_FILTER, ldb_dn_get_linearized(dn));

    ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
                    attrs, LOCAL_CONTAINER_FILTER);
    if (ret != EOK) {
        DEBUG(SSSDBG_TRACE_LIBS,
              "ldb_search returned %d: %s\n", ret, ldb_strerror(ret));
        goto done;
    }

    if (res->count == 1) {
        DEBUG(SSSDBG_TRACE_INTERNAL,
              "Searching for children of [%s]\n", ldb_dn_get_linearized(dn));
        ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL,
                         attrs, NULL);
        if (ret != EOK) {
            DEBUG(SSSDBG_TRACE_LIBS,
                  "ldb_search returned %d: %s\n", ret, ldb_strerror(ret));
            goto done;
        }

        if (res->count > 0) {
            ret = EEXIST;
            DEBUG(SSSDBG_OP_FAILURE,
                  "Failed to remove '%s': Container is not empty\n",
                  ldb_dn_get_linearized(dn));

            goto done;
        }
    }

    ret = ldb_delete(lctx->ldb, dn);
    if (ret != EOK) {
        DEBUG(SSSDBG_TRACE_LIBS,
              "ldb_delete returned %d: %s\n", ret, ldb_strerror(ret));
        /* fallthrough */
    }
    ret = sysdb_error_to_errno(ret);

done:
    talloc_free(tmp_ctx);
    return ret;
}