Exemple #1
0
/* Convert a binary SID to a character string */
wbcErr wbcSidToString(const struct wbcDomainSid *sid,
		      char **sid_string)
{
	char buf[WBC_SID_STRING_BUFLEN];
	char *result;
	int len;

	if (!sid) {
		return WBC_ERR_INVALID_SID;
	}

	len = wbcSidToStringBuf(sid, buf, sizeof(buf));

	if (len+1 > sizeof(buf)) {
		return WBC_ERR_INVALID_SID;
	}

	result = (char *)wbcAllocateMemory(len+1, 1, NULL);
	if (result == NULL) {
		return WBC_ERR_NO_MEMORY;
	}
	memcpy(result, buf, len+1);

	*sid_string = result;
	return WBC_ERR_SUCCESS;
}
Exemple #2
0
static wbcErr wbc_create_error_info(const struct winbindd_response *resp,
				    struct wbcAuthErrorInfo **_e)
{
	wbcErr wbc_status = WBC_ERR_SUCCESS;
	struct wbcAuthErrorInfo *e;

	e = (struct wbcAuthErrorInfo *)wbcAllocateMemory(
		1, sizeof(struct wbcAuthErrorInfo),
		wbcAuthErrorInfoDestructor);
	BAIL_ON_PTR_ERROR(e, wbc_status);

	e->nt_status = resp->data.auth.nt_status;
	e->pam_error = resp->data.auth.pam_error;
	e->authoritative = resp->data.auth.authoritative;
	e->nt_string = strdup(resp->data.auth.nt_status_string);
	BAIL_ON_PTR_ERROR(e->nt_string, wbc_status);

	e->display_string = strdup(resp->data.auth.error_string);
	BAIL_ON_PTR_ERROR(e->display_string, wbc_status);

	*_e = e;
	e = NULL;

done:
	wbcFreeMemory(e);
	return wbc_status;
}
Exemple #3
0
static wbcErr wbc_create_domain_controller_info_ex(const struct winbindd_response *resp,
						   struct wbcDomainControllerInfoEx **_i)
{
	wbcErr wbc_status = WBC_ERR_SUCCESS;
	struct wbcDomainControllerInfoEx *i;
	struct wbcGuid guid;

	i = (struct wbcDomainControllerInfoEx *)wbcAllocateMemory(
		1, sizeof(struct wbcDomainControllerInfoEx),
		wbcDomainControllerInfoExDestructor);
	BAIL_ON_PTR_ERROR(i, wbc_status);

	i->dc_unc = strdup(resp->data.dsgetdcname.dc_unc);
	BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status);

	i->dc_address = strdup(resp->data.dsgetdcname.dc_address);
	BAIL_ON_PTR_ERROR(i->dc_address, wbc_status);

	i->dc_address_type = resp->data.dsgetdcname.dc_address_type;

	wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid);
	if (WBC_ERROR_IS_OK(wbc_status)) {
		i->domain_guid = (struct wbcGuid *)malloc(
			sizeof(struct wbcGuid));
		BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status);

		*i->domain_guid = guid;
	}

	i->domain_name = strdup(resp->data.dsgetdcname.domain_name);
	BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);

	if (resp->data.dsgetdcname.forest_name[0] != '\0') {
		i->forest_name = strdup(resp->data.dsgetdcname.forest_name);
		BAIL_ON_PTR_ERROR(i->forest_name, wbc_status);
	}

	i->dc_flags = resp->data.dsgetdcname.dc_flags;

	if (resp->data.dsgetdcname.dc_site_name[0] != '\0') {
		i->dc_site_name = strdup(resp->data.dsgetdcname.dc_site_name);
		BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status);
	}

	if (resp->data.dsgetdcname.client_site_name[0] != '\0') {
		i->client_site_name = strdup(
			resp->data.dsgetdcname.client_site_name);
		BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status);
	}

	*_i = i;
	i = NULL;

done:
	if (i != NULL) {
		wbcFreeMemory(i);
	}
	return wbc_status;
}
Exemple #4
0
/* Initialize a named blob and add to list of blobs */
wbcErr wbcAddNamedBlob(size_t *num_blobs,
		       struct wbcNamedBlob **pblobs,
		       const char *name,
		       uint32_t flags,
		       uint8_t *data,
		       size_t length)
{
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	struct wbcNamedBlob *blobs, *blob;

	if (name == NULL) {
		return WBC_ERR_INVALID_PARAM;
	}

	/*
	 * Overallocate the b->name==NULL terminator for
	 * wbcNamedBlobDestructor
	 */
	blobs = (struct wbcNamedBlob *)wbcAllocateMemory(
		*num_blobs + 2, sizeof(struct wbcNamedBlob),
		wbcNamedBlobDestructor);

	if (blobs == NULL) {
		return WBC_ERR_NO_MEMORY;
	}

	if (*pblobs != NULL) {
		struct wbcNamedBlob *old = *pblobs;
		memcpy(blobs, old, sizeof(struct wbcNamedBlob) * (*num_blobs));
		if (*num_blobs != 0) {
			/* end indicator for wbcNamedBlobDestructor */
			old[0].name = NULL;
		}
		wbcFreeMemory(old);
	}
	*pblobs = blobs;

	blob = &blobs[*num_blobs];

	blob->name = strdup(name);
	BAIL_ON_PTR_ERROR(blob->name, wbc_status);
	blob->flags = flags;

	blob->blob.length = length;
	blob->blob.data	= (uint8_t *)malloc(length);
	BAIL_ON_PTR_ERROR(blob->blob.data, wbc_status);
	memcpy(blob->blob.data, data, length);

	*num_blobs += 1;
	*pblobs = blobs;
	blobs = NULL;

	wbc_status = WBC_ERR_SUCCESS;
done:
	wbcFreeMemory(blobs);
	return wbc_status;
}
Exemple #5
0
wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
{
	struct winbindd_request request;
	struct winbindd_response response;
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	struct wbcDomainInfo *info = NULL;

	if (!domain || !dinfo) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	/* Initialize request */

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	strncpy(request.domain_name, domain,
		sizeof(request.domain_name)-1);

	wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_INFO,
					&request,
					&response);
	BAIL_ON_WBC_ERROR(wbc_status);

	info = (struct wbcDomainInfo *)wbcAllocateMemory(
		1, sizeof(struct wbcDomainInfo), wbcDomainInfoDestructor);
	BAIL_ON_PTR_ERROR(info, wbc_status);

	info->short_name = strdup(response.data.domain_info.name);
	BAIL_ON_PTR_ERROR(info->short_name, wbc_status);

	info->dns_name = strdup(response.data.domain_info.alt_name);
	BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);

	wbc_status = wbcStringToSid(response.data.domain_info.sid,
				    &info->sid);
	BAIL_ON_WBC_ERROR(wbc_status);

	if (response.data.domain_info.native_mode)
		info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
	if (response.data.domain_info.active_directory)
		info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
	if (response.data.domain_info.primary)
		info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;

	*dinfo = info;
	info = NULL;

	wbc_status = WBC_ERR_SUCCESS;

 done:
	wbcFreeMemory(info);
	return wbc_status;
}
Exemple #6
0
/*
 * Trigger a no-op NETLOGON call. Lightweight version of
 * wbcCheckTrustCredentials, optionally return attempted DC
 */
wbcErr wbcPingDc2(const char *domain, struct wbcAuthErrorInfo **error,
		  char **dcname)
{
	struct winbindd_request request;
	struct winbindd_response response;
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;

	if (domain) {
		/*
		 * the current protocol doesn't support
		 * specifying a domain
		 */
		wbc_status = WBC_ERR_NOT_IMPLEMENTED;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	/* Send request */

	wbc_status = wbcRequestResponse(WINBINDD_PING_DC,
					&request,
					&response);

	if (dcname && response.extra_data.data) {
		size_t len;

		len = response.length - sizeof(struct winbindd_response);
		*dcname = wbcAllocateMemory(1, len, NULL);
		BAIL_ON_PTR_ERROR(*dcname, wbc_status);

		strlcpy(*dcname, response.extra_data.data, len);
	}

	if (response.data.auth.nt_status != 0) {
		if (error) {
			wbc_status = wbc_create_error_info(&response,
							   error);
			BAIL_ON_WBC_ERROR(wbc_status);
		}

		wbc_status = WBC_ERR_AUTH_ERROR;
		BAIL_ON_WBC_ERROR(wbc_status);
	}
	BAIL_ON_WBC_ERROR(wbc_status);

 done:
	return wbc_status;
}
Exemple #7
0
/* Enumerate the domain trusts known by Winbind */
wbcErr wbcLookupDomainController(const char *domain,
				 uint32_t flags,
				struct wbcDomainControllerInfo **dc_info)
{
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	struct winbindd_request request;
	struct winbindd_response response;
	struct wbcDomainControllerInfo *dc = NULL;

	/* validate input params */

	if (!domain || !dc_info) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	strncpy(request.data.dsgetdcname.domain_name, domain,
		sizeof(request.data.dsgetdcname.domain_name)-1);

	request.flags = flags;

	dc = (struct wbcDomainControllerInfo *)wbcAllocateMemory(
		 1, sizeof(struct wbcDomainControllerInfo),
		wbcDomainControllerInfoDestructor);
	BAIL_ON_PTR_ERROR(dc, wbc_status);

	/* Send request */

	wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME,
					&request,
					&response);
	BAIL_ON_WBC_ERROR(wbc_status);

	dc->dc_name = strdup(response.data.dsgetdcname.dc_unc);
	BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);

	*dc_info = dc;
	dc = NULL;

done:
	wbcFreeMemory(dc);
	return wbc_status;
}
Exemple #8
0
/*
 * Trigger a no-op NETLOGON call. Lightweight version of
 * wbcCheckTrustCredentials, optionally return attempted DC
 */
wbcErr wbcCtxPingDc2(struct wbcContext *ctx, const char *domain,
		     struct wbcAuthErrorInfo **error, char **dcname)
{
	struct winbindd_request request;
	struct winbindd_response response;
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	if (domain) {
		strncpy(request.domain_name, domain,
			sizeof(request.domain_name)-1);
	}

	/* Send request */

	wbc_status = wbcRequestResponse(ctx, WINBINDD_PING_DC,
					&request,
					&response);

	if (dcname && response.extra_data.data) {
		size_t len;

		len = response.length - sizeof(struct winbindd_response);
		*dcname = wbcAllocateMemory(1, len, NULL);
		BAIL_ON_PTR_ERROR(*dcname, wbc_status);

		strlcpy(*dcname, response.extra_data.data, len);
	}

	if (response.data.auth.nt_status != 0) {
		if (error) {
			wbc_status = wbc_create_error_info(&response,
							   error);
			BAIL_ON_WBC_ERROR(wbc_status);
		}

		wbc_status = WBC_ERR_AUTH_ERROR;
		BAIL_ON_WBC_ERROR(wbc_status);
	}
	BAIL_ON_WBC_ERROR(wbc_status);

 done:
	return wbc_status;
}
Exemple #9
0
static wbcErr wbc_create_logon_info(struct winbindd_response *resp,
				    struct wbcLogonUserInfo **_i)
{
	wbcErr wbc_status = WBC_ERR_SUCCESS;
	struct wbcLogonUserInfo *i;

	i = (struct wbcLogonUserInfo *)wbcAllocateMemory(
		1, sizeof(struct wbcLogonUserInfo),
		wbcLogonUserInfoDestructor);
	BAIL_ON_PTR_ERROR(i, wbc_status);

	wbc_status = wbc_create_auth_info(resp, &i->info);
	BAIL_ON_WBC_ERROR(wbc_status);

	if (resp->data.auth.krb5ccname[0] != '\0') {
		wbc_status = wbcAddNamedBlob(&i->num_blobs,
					     &i->blobs,
					     "krb5ccname",
					     0,
					     (uint8_t *)resp->data.auth.krb5ccname,
					     strlen(resp->data.auth.krb5ccname)+1);
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	if (resp->data.auth.unix_username[0] != '\0') {
		wbc_status = wbcAddNamedBlob(&i->num_blobs,
					     &i->blobs,
					     "unix_username",
					     0,
					     (uint8_t *)resp->data.auth.unix_username,
					     strlen(resp->data.auth.unix_username)+1);
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	*_i = i;
	i = NULL;
done:
	wbcFreeMemory(i);
	return wbc_status;
}
Exemple #10
0
static wbcErr wbc_create_password_policy_info(const struct winbindd_response *resp,
					      struct wbcUserPasswordPolicyInfo **_i)
{
	wbcErr wbc_status = WBC_ERR_SUCCESS;
	struct wbcUserPasswordPolicyInfo *i;

	i = (struct wbcUserPasswordPolicyInfo *)wbcAllocateMemory(
		1, sizeof(struct wbcUserPasswordPolicyInfo), NULL);
	BAIL_ON_PTR_ERROR(i, wbc_status);

	i->min_passwordage	= resp->data.auth.policy.min_passwordage;
	i->min_length_password	= resp->data.auth.policy.min_length_password;
	i->password_history	= resp->data.auth.policy.password_history;
	i->password_properties	= resp->data.auth.policy.password_properties;
	i->expire		= resp->data.auth.policy.expire;

	*_i = i;
	i = NULL;

done:
	wbcFreeMemory(i);
	return wbc_status;
}
Exemple #11
0
/* Get alias membership for sids */
wbcErr wbcGetSidAliases(const struct wbcDomainSid *dom_sid,
			struct wbcDomainSid *sids,
			uint32_t num_sids,
			uint32_t **alias_rids,
			uint32_t *num_alias_rids)
{
	uint32_t i;
	const char *s;
	struct winbindd_request request;
	struct winbindd_response response;
	ssize_t extra_data_len = 0;
	char * extra_data = NULL;
	ssize_t buflen = 0;
	struct wbcDomainSid sid;
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	uint32_t * rids = NULL;

	/* Initialise request */

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	if (!dom_sid) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		goto done;
	}

	wbcSidToStringBuf(dom_sid, request.data.sid, sizeof(request.data.sid));

	/* Lets assume each sid is around 57 characters
	 * S-1-5-21-AAAAAAAAAAA-BBBBBBBBBBB-CCCCCCCCCCC-DDDDDDDDDDD\n */
	buflen = 57 * num_sids;
	extra_data = (char *)malloc(buflen);
	if (!extra_data) {
		wbc_status = WBC_ERR_NO_MEMORY;
		goto done;
	}

	/* Build the sid list */
	for (i=0; i<num_sids; i++) {
		char sid_str[WBC_SID_STRING_BUFLEN];
		size_t sid_len;

		sid_len = wbcSidToStringBuf(&sids[i], sid_str, sizeof(sid_str));

		if (buflen < extra_data_len + sid_len + 2) {
			buflen *= 2;
			extra_data = (char *)realloc(extra_data, buflen);
			if (!extra_data) {
				wbc_status = WBC_ERR_NO_MEMORY;
				BAIL_ON_WBC_ERROR(wbc_status);
			}
		}

		strncpy(&extra_data[extra_data_len], sid_str,
			buflen - extra_data_len);
		extra_data_len += sid_len;
		extra_data[extra_data_len++] = '\n';
		extra_data[extra_data_len] = '\0';
	}
	extra_data_len += 1;

	request.extra_data.data = extra_data;
	request.extra_len = extra_data_len;

	wbc_status = wbcRequestResponse(WINBINDD_GETSIDALIASES,
					&request,
					&response);
	BAIL_ON_WBC_ERROR(wbc_status);

	if (response.data.num_entries &&
	    !response.extra_data.data) {
		wbc_status = WBC_ERR_INVALID_RESPONSE;
		goto done;
	}

	rids = (uint32_t *)wbcAllocateMemory(response.data.num_entries,
					     sizeof(uint32_t), NULL);
	BAIL_ON_PTR_ERROR(sids, wbc_status);

	s = (const char *)response.extra_data.data;
	for (i = 0; i < response.data.num_entries; i++) {
		char *n = strchr(s, '\n');
		if (n) {
			*n = '\0';
		}
		wbc_status = wbcStringToSid(s, &sid);
		BAIL_ON_WBC_ERROR(wbc_status);
		wbc_status = _sid_to_rid(&sid, &rids[i]);
		BAIL_ON_WBC_ERROR(wbc_status);
		s += strlen(s) + 1;
	}

	*num_alias_rids = response.data.num_entries;
	*alias_rids = rids;
	rids = NULL;
	wbc_status = WBC_ERR_SUCCESS;

 done:
	free(extra_data);
	winbindd_free_response(&response);
	wbcFreeMemory(rids);
	return wbc_status;
}
Exemple #12
0
/* Enumerate the domain trusts known by Winbind */
wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
{
	struct winbindd_response response;
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	char *p = NULL;
	char *extra_data = NULL;
	struct wbcDomainInfo *d_list = NULL;
	int i = 0;

	*domains = NULL;
	*num_domains = 0;

	ZERO_STRUCT(response);

	/* Send request */

	wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM,
					NULL,
					&response);
	BAIL_ON_WBC_ERROR(wbc_status);

	/* Decode the response */

	p = (char *)response.extra_data.data;

	if ((p == NULL) || (strlen(p) == 0)) {
		/* We should always at least get back our
		   own SAM domain */

		wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	d_list = (struct wbcDomainInfo *)wbcAllocateMemory(
		response.data.num_entries + 1,sizeof(struct wbcDomainInfo),
		wbcDomainInfoListDestructor);
	BAIL_ON_PTR_ERROR(d_list, wbc_status);

	extra_data = strdup((char*)response.extra_data.data);
	BAIL_ON_PTR_ERROR(extra_data, wbc_status);

	p = extra_data;

	/* Outer loop processes the list of domain information */

	for (i=0; i<response.data.num_entries && p; i++) {
		char *next = strchr(p, '\n');

		if (next) {
			*next = '\0';
			next++;
		}

		wbc_status = process_domain_info_string(&d_list[i], p);
		BAIL_ON_WBC_ERROR(wbc_status);

		p = next;
	}

	*domains = d_list;
	d_list = NULL;
	*num_domains = i;

 done:
	winbindd_free_response(&response);
	wbcFreeMemory(d_list);
	free(extra_data);
	return wbc_status;
}
Exemple #13
0
/* Get the groups a user belongs to */
wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
			 bool domain_groups_only,
			 uint32_t *num_sids,
			 struct wbcDomainSid **_sids)
{
	uint32_t i;
	const char *s;
	struct winbindd_request request;
	struct winbindd_response response;
	struct wbcDomainSid *sids = NULL;
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	int cmd;

	/* Initialise request */

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	if (!user_sid) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	wbcSidToStringBuf(user_sid, request.data.sid, sizeof(request.data.sid));

	if (domain_groups_only) {
		cmd = WINBINDD_GETUSERDOMGROUPS;
	} else {
		cmd = WINBINDD_GETUSERSIDS;
	}

	wbc_status = wbcRequestResponse(cmd,
					&request,
					&response);
	BAIL_ON_WBC_ERROR(wbc_status);

	if (response.data.num_entries &&
	    !response.extra_data.data) {
		wbc_status = WBC_ERR_INVALID_RESPONSE;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	sids = (struct wbcDomainSid *)wbcAllocateMemory(
		response.data.num_entries, sizeof(struct wbcDomainSid),
		NULL);
	BAIL_ON_PTR_ERROR(sids, wbc_status);

	s = (const char *)response.extra_data.data;
	for (i = 0; i < response.data.num_entries; i++) {
		char *n = strchr(s, '\n');
		if (n) {
			*n = '\0';
		}
		wbc_status = wbcStringToSid(s, &sids[i]);
		BAIL_ON_WBC_ERROR(wbc_status);
		s += strlen(s) + 1;
	}

	*num_sids = response.data.num_entries;
	*_sids = sids;
	sids = NULL;
	wbc_status = WBC_ERR_SUCCESS;

 done:
	winbindd_free_response(&response);
	if (sids) {
		wbcFreeMemory(sids);
	}

	return wbc_status;
}
Exemple #14
0
wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
		     int num_rids,
		     uint32_t *rids,
		     const char **pp_domain_name,
		     const char ***pnames,
		     enum wbcSidType **ptypes)
{
	size_t i, len, ridbuf_size;
	char *ridlist;
	char *p;
	struct winbindd_request request;
	struct winbindd_response response;
	char *domain_name = NULL;
	const char **names = NULL;
	enum wbcSidType *types = NULL;
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;

	/* Initialise request */

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	if (!dom_sid || (num_rids == 0)) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	wbcSidToStringBuf(dom_sid, request.data.sid, sizeof(request.data.sid));

	/* Even if all the Rids were of maximum 32bit values,
	   we would only have 11 bytes per rid in the final array
	   ("4294967296" + \n).  Add one more byte for the
	   terminating '\0' */

	ridbuf_size = (sizeof(char)*11) * num_rids + 1;

	ridlist = (char *)malloc(ridbuf_size);
	BAIL_ON_PTR_ERROR(ridlist, wbc_status);

	len = 0;
	for (i=0; i<num_rids; i++) {
		len += snprintf(ridlist + len, ridbuf_size - len, "%u\n",
				rids[i]);
	}
	ridlist[len] = '\0';
	len += 1;

	request.extra_data.data = ridlist;
	request.extra_len = len;

	wbc_status = wbcRequestResponse(WINBINDD_LOOKUPRIDS,
					&request,
					&response);
	free(ridlist);
	BAIL_ON_WBC_ERROR(wbc_status);

	domain_name = wbcStrDup(response.data.domain_name);
	BAIL_ON_PTR_ERROR(domain_name, wbc_status);

	names = wbcAllocateStringArray(num_rids);
	BAIL_ON_PTR_ERROR(names, wbc_status);

	types = (enum wbcSidType *)wbcAllocateMemory(
		num_rids, sizeof(enum wbcSidType), NULL);
	BAIL_ON_PTR_ERROR(types, wbc_status);

	p = (char *)response.extra_data.data;

	for (i=0; i<num_rids; i++) {
		char *q;

		if (*p == '\0') {
			wbc_status = WBC_ERR_INVALID_RESPONSE;
			goto done;
		}

		types[i] = (enum wbcSidType)strtoul(p, &q, 10);

		if (*q != ' ') {
			wbc_status = WBC_ERR_INVALID_RESPONSE;
			goto done;
		}

		p = q+1;

		if ((q = strchr(p, '\n')) == NULL) {
			wbc_status = WBC_ERR_INVALID_RESPONSE;
			goto done;
		}

		*q = '\0';

		names[i] = strdup(p);
		BAIL_ON_PTR_ERROR(names[i], wbc_status);

		p = q+1;
	}

	if (*p != '\0') {
		wbc_status = WBC_ERR_INVALID_RESPONSE;
		goto done;
	}

	wbc_status = WBC_ERR_SUCCESS;

 done:
	winbindd_free_response(&response);

	if (WBC_ERROR_IS_OK(wbc_status)) {
		*pp_domain_name = domain_name;
		*pnames = names;
		*ptypes = types;
	}
	else {
		wbcFreeMemory(domain_name);
		wbcFreeMemory(names);
		wbcFreeMemory(types);
	}

	return wbc_status;
}
Exemple #15
0
wbcErr wbcLookupSids(const struct wbcDomainSid *sids, int num_sids,
		     struct wbcDomainInfo **pdomains, int *pnum_domains,
		     struct wbcTranslatedName **pnames)
{
	struct winbindd_request request;
	struct winbindd_response response;
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	int buflen, i, extra_len, num_domains, num_names;
	char *sidlist, *p, *q, *extra_data;
	struct wbcDomainInfo *domains = NULL;
	struct wbcTranslatedName *names = NULL;

	buflen = num_sids * (WBC_SID_STRING_BUFLEN + 1) + 1;

	sidlist = (char *)malloc(buflen);
	if (sidlist == NULL) {
		return WBC_ERR_NO_MEMORY;
	}

	p = sidlist;

	for (i=0; i<num_sids; i++) {
		int remaining;
		int len;

		remaining = buflen - (p - sidlist);

		len = wbcSidToStringBuf(&sids[i], p, remaining);
		if (len > remaining) {
			free(sidlist);
			return WBC_ERR_UNKNOWN_FAILURE;
		}

		p += len;
		*p++ = '\n';
	}
	*p++ = '\0';

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	request.extra_data.data = sidlist;
	request.extra_len = p - sidlist;

	wbc_status = wbcRequestResponse(WINBINDD_LOOKUPSIDS,
					&request, &response);
	free(sidlist);
	if (!WBC_ERROR_IS_OK(wbc_status)) {
		return wbc_status;
	}

	extra_len = response.length - sizeof(struct winbindd_response);
	extra_data = (char *)response.extra_data.data;

	if ((extra_len <= 0) || (extra_data[extra_len-1] != '\0')) {
		goto wbc_err_invalid;
	}

	p = extra_data;

	num_domains = strtoul(p, &q, 10);
	if (*q != '\n') {
		goto wbc_err_invalid;
	}
	p = q+1;

	domains = (struct wbcDomainInfo *)wbcAllocateMemory(
		num_domains+1, sizeof(struct wbcDomainInfo),
		wbcDomainInfosDestructor);
	if (domains == NULL) {
		wbc_status = WBC_ERR_NO_MEMORY;
		goto fail;
	}

	for (i=0; i<num_domains; i++) {

		q = strchr(p, ' ');
		if (q == NULL) {
			goto wbc_err_invalid;
		}
		*q = '\0';
		wbc_status = wbcStringToSid(p, &domains[i].sid);
		if (!WBC_ERROR_IS_OK(wbc_status)) {
			goto fail;
		}
		p = q+1;

		q = strchr(p, '\n');
		if (q == NULL) {
			goto wbc_err_invalid;
		}
		*q = '\0';
		domains[i].short_name = wbcStrDup(p);
		if (domains[i].short_name == NULL) {
			wbc_status = WBC_ERR_NO_MEMORY;
			goto fail;
		}
		p = q+1;
	}

	num_names = strtoul(p, &q, 10);
	if (*q != '\n') {
		goto wbc_err_invalid;
	}
	p = q+1;

	if (num_names != num_sids) {
		goto wbc_err_invalid;
	}

	names = (struct wbcTranslatedName *)wbcAllocateMemory(
		num_names+1, sizeof(struct wbcTranslatedName),
		wbcTranslatedNamesDestructor);
	if (names == NULL) {
		wbc_status = WBC_ERR_NO_MEMORY;
		goto fail;
	}

	for (i=0; i<num_names; i++) {

		names[i].domain_index = strtoul(p, &q, 10);
		if (*q != ' ') {
			goto wbc_err_invalid;
		}
		p = q+1;

		names[i].type = strtoul(p, &q, 10);
		if (*q != ' ') {
			goto wbc_err_invalid;
		}
		p = q+1;

		q = strchr(p, '\n');
		if (q == NULL) {
			goto wbc_err_invalid;
		}
		*q = '\0';
		names[i].name = wbcStrDup(p);
		if (names[i].name == NULL) {
			wbc_status = WBC_ERR_NO_MEMORY;
			goto fail;
		}
		p = q+1;
	}
	if (*p != '\0') {
		goto wbc_err_invalid;
	}

	*pdomains = domains;
	*pnames = names;
	winbindd_free_response(&response);
	return WBC_ERR_SUCCESS;

wbc_err_invalid:
	wbc_status = WBC_ERR_INVALID_RESPONSE;
fail:
	winbindd_free_response(&response);
	wbcFreeMemory(domains);
	wbcFreeMemory(names);
	return wbc_status;
}
Exemple #16
0
static wbcErr wbc_create_auth_info(const struct winbindd_response *resp,
				   struct wbcAuthUserInfo **_i)
{
	wbcErr wbc_status = WBC_ERR_SUCCESS;
	struct wbcAuthUserInfo *i;
	struct wbcDomainSid domain_sid;
	char *p;
	uint32_t sn = 0;
	uint32_t j;

	i = (struct wbcAuthUserInfo *)wbcAllocateMemory(
		1, sizeof(struct wbcAuthUserInfo),
		wbcAuthUserInfoDestructor);
	BAIL_ON_PTR_ERROR(i, wbc_status);

	i->user_flags	= resp->data.auth.info3.user_flgs;

	i->account_name	= strdup(resp->data.auth.info3.user_name);
	BAIL_ON_PTR_ERROR(i->account_name, wbc_status);
	if (resp->data.auth.validation_level == 6) {
		i->user_principal = strdup(resp->data.auth.info6.principal_name);
		BAIL_ON_PTR_ERROR(i->user_principal, wbc_status);
	} else {
		i->user_principal = NULL;
	}
	i->full_name	= strdup(resp->data.auth.info3.full_name);
	BAIL_ON_PTR_ERROR(i->full_name, wbc_status);
	i->domain_name	= strdup(resp->data.auth.info3.logon_dom);
	BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
	if (resp->data.auth.validation_level == 6) {
		i->dns_domain_name = strdup(resp->data.auth.info6.dns_domainname);
		BAIL_ON_PTR_ERROR(i->dns_domain_name, wbc_status);
	} else {
		i->dns_domain_name = NULL;
	}

	i->acct_flags	= resp->data.auth.info3.acct_flags;
	memcpy(i->user_session_key,
	       resp->data.auth.user_session_key,
	       sizeof(i->user_session_key));
	memcpy(i->lm_session_key,
	       resp->data.auth.first_8_lm_hash,
	       sizeof(i->lm_session_key));

	i->logon_count		= resp->data.auth.info3.logon_count;
	i->bad_password_count	= resp->data.auth.info3.bad_pw_count;

	i->logon_time		= resp->data.auth.info3.logon_time;
	i->logoff_time		= resp->data.auth.info3.logoff_time;
	i->kickoff_time		= resp->data.auth.info3.kickoff_time;
	i->pass_last_set_time	= resp->data.auth.info3.pass_last_set_time;
	i->pass_can_change_time	= resp->data.auth.info3.pass_can_change_time;
	i->pass_must_change_time= resp->data.auth.info3.pass_must_change_time;

	i->logon_server	= strdup(resp->data.auth.info3.logon_srv);
	BAIL_ON_PTR_ERROR(i->logon_server, wbc_status);
	i->logon_script	= strdup(resp->data.auth.info3.logon_script);
	BAIL_ON_PTR_ERROR(i->logon_script, wbc_status);
	i->profile_path	= strdup(resp->data.auth.info3.profile_path);
	BAIL_ON_PTR_ERROR(i->profile_path, wbc_status);
	i->home_directory= strdup(resp->data.auth.info3.home_dir);
	BAIL_ON_PTR_ERROR(i->home_directory, wbc_status);
	i->home_drive	= strdup(resp->data.auth.info3.dir_drive);
	BAIL_ON_PTR_ERROR(i->home_drive, wbc_status);

	i->num_sids	= 2;
	i->num_sids 	+= resp->data.auth.info3.num_groups;
	i->num_sids	+= resp->data.auth.info3.num_other_sids;

	i->sids	= (struct wbcSidWithAttr *)calloc(
		sizeof(struct wbcSidWithAttr), i->num_sids);
	BAIL_ON_PTR_ERROR(i->sids, wbc_status);

	wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid,
				    &domain_sid);
	BAIL_ON_WBC_ERROR(wbc_status);

	sn = 0;
	if (!sid_attr_compose(&i->sids[sn], &domain_sid,
			      resp->data.auth.info3.user_rid, 0)) {
		wbc_status = WBC_ERR_INVALID_SID;
		goto done;
	}
	sn++;
	if (!sid_attr_compose(&i->sids[sn], &domain_sid,
			      resp->data.auth.info3.group_rid, 0)) {
		wbc_status = WBC_ERR_INVALID_SID;
		goto done;
	}
	sn++;

	p = (char *)resp->extra_data.data;
	if (!p) {
		wbc_status = WBC_ERR_INVALID_RESPONSE;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	for (j=0; j < resp->data.auth.info3.num_groups; j++) {
		uint32_t rid;
		uint32_t attrs;
		int ret;
		char *s = p;
		char *e = strchr(p, '\n');
		if (!e) {
			wbc_status = WBC_ERR_INVALID_RESPONSE;
			BAIL_ON_WBC_ERROR(wbc_status);
		}
		e[0] = '\0';
		p = &e[1];

		ret = sscanf(s, "0x%08X:0x%08X", &rid, &attrs);
		if (ret != 2) {
			wbc_status = WBC_ERR_INVALID_RESPONSE;
			BAIL_ON_WBC_ERROR(wbc_status);
		}

		if (!sid_attr_compose(&i->sids[sn], &domain_sid,
				      rid, attrs)) {
			wbc_status = WBC_ERR_INVALID_SID;
			goto done;
		}
		sn++;
	}

	for (j=0; j < resp->data.auth.info3.num_other_sids; j++) {
		uint32_t attrs;
		int ret;
		char *s = p;
		char *a;
		char *e = strchr(p, '\n');
		if (!e) {
			wbc_status = WBC_ERR_INVALID_RESPONSE;
			BAIL_ON_WBC_ERROR(wbc_status);
		}
		e[0] = '\0';
		p = &e[1];

		e = strchr(s, ':');
		if (!e) {
			wbc_status = WBC_ERR_INVALID_RESPONSE;
			BAIL_ON_WBC_ERROR(wbc_status);
		}
		e[0] = '\0';
		a = &e[1];

		ret = sscanf(a, "0x%08X",
			     &attrs);
		if (ret != 1) {
			wbc_status = WBC_ERR_INVALID_RESPONSE;
			BAIL_ON_WBC_ERROR(wbc_status);
		}

		wbc_status = wbcStringToSid(s, &i->sids[sn].sid);
		BAIL_ON_WBC_ERROR(wbc_status);

		i->sids[sn].attributes = attrs;
		sn++;
	}

	i->num_sids = sn;

	*_i = i;
	i = NULL;
done:
	wbcFreeMemory(i);
	return wbc_status;
}
Exemple #17
0
wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
             int num_rids,
             uint32_t *rids,
             const char **pp_domain_name,
             const char ***pnames,
             enum wbcSidType **ptypes)
{
    struct wbcDomainSid obj_sid = {0};
    size_t c;
    wbcErr err;
    char *domain;
    char *name;
    enum wbcSidType type;
    const char **names = NULL;
    enum wbcSidType *types = NULL;

    obj_sid.sid_rev_num = dom_sid->sid_rev_num;
    obj_sid.num_auths = dom_sid->num_auths + 1;
    for (c = 0; c < 6; c++) {
        obj_sid.id_auth[c] = dom_sid->id_auth[c];
    }
    for (c = 0; c < WBC_MAXSUBAUTHS; c++) {
        obj_sid.sub_auths[c] = dom_sid->sub_auths[c];
    }

    names = wbcAllocateStringArray(num_rids + 1);
    if (names == NULL) {
        err = WBC_ERR_NO_MEMORY;
        goto done;
    }

    types = wbcAllocateMemory(num_rids + 1, sizeof(enum wbcSidType), NULL);
    if (types == NULL) {
        err = WBC_ERR_NO_MEMORY;
        goto done;
    }

    for (c = 0; c < num_rids; c++) {
        obj_sid.sub_auths[obj_sid.num_auths - 1] = rids[c];

        err = wbcLookupSid(&obj_sid, &domain, &name, &type);
        if (err != WBC_ERR_SUCCESS) {
            goto done;
        }

        names[c] = strdup(name);
        wbcFreeMemory(name);
        if (names[c] == NULL) {
            err = WBC_ERR_NO_MEMORY;
            goto done;
        }
        types[c] = type;

        if (c == 0) {
            *pp_domain_name = domain;
        } else {
            wbcFreeMemory(domain);
        }
    }

    *pnames = names;
    *ptypes = types;

    err = WBC_ERR_SUCCESS;

done:
    if (err != WBC_ERR_SUCCESS) {
        wbcFreeMemory(types);
        wbcFreeMemory(names);
    }

    return err;
}
Exemple #18
0
/* Authenticate a user with cached credentials */
wbcErr wbcCtxCredentialCache(struct wbcContext *ctx,
			     struct wbcCredentialCacheParams *params,
                             struct wbcCredentialCacheInfo **info,
                             struct wbcAuthErrorInfo **error)
{
	wbcErr status = WBC_ERR_UNKNOWN_FAILURE;
	struct wbcCredentialCacheInfo *result = NULL;
	struct winbindd_request request;
	struct winbindd_response response;
	struct wbcNamedBlob *initial_blob = NULL;
	struct wbcNamedBlob *challenge_blob = NULL;
	size_t i;

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	*info = NULL;

	if (error != NULL) {
		*error = NULL;
	}
	if ((params == NULL)
	    || (params->account_name == NULL)
	    || (params->level != WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP)) {
		status = WBC_ERR_INVALID_PARAM;
		goto fail;
	}

	for (i=0; i<params->num_blobs; i++) {
		/*
		 * Older callers may used to provide the NEGOTIATE request
		 * as "initial_blob", but it was completely ignored by winbindd.
		 *
		 * So we keep ignoring it.
		 *
		 * A new callers that is capable to support "new_spnego",
		 * will provide the NEGOTIATE request as "negotiate_blob"
		 * instead.
		 */
		if (strcasecmp(params->blobs[i].name, "negotiate_blob") == 0) {
			if (initial_blob != NULL) {
				status = WBC_ERR_INVALID_PARAM;
				goto fail;
			}
			initial_blob = &params->blobs[i];
			continue;
		}
		if (strcasecmp(params->blobs[i].name, "challenge_blob") == 0) {
			if (challenge_blob != NULL) {
				status = WBC_ERR_INVALID_PARAM;
				goto fail;
			}
			challenge_blob = &params->blobs[i];
			continue;
		}
	}

	if (params->domain_name != NULL) {
		status = wbcRequestResponse(ctx, WINBINDD_INFO,
					    NULL, &response);
		if (!WBC_ERROR_IS_OK(status)) {
			goto fail;
		}
		snprintf(request.data.ccache_ntlm_auth.user,
			 sizeof(request.data.ccache_ntlm_auth.user)-1,
			 "%s%c%s", params->domain_name,
			 response.data.info.winbind_separator,
			 params->account_name);
	} else {
		strncpy(request.data.ccache_ntlm_auth.user,
			params->account_name,
			sizeof(request.data.ccache_ntlm_auth.user)-1);
	}
	request.data.ccache_ntlm_auth.uid = getuid();

	request.data.ccache_ntlm_auth.initial_blob_len = 0;
	request.data.ccache_ntlm_auth.challenge_blob_len = 0;
	request.extra_len = 0;

	if (initial_blob != NULL) {
		request.data.ccache_ntlm_auth.initial_blob_len =
			initial_blob->blob.length;
		request.extra_len += initial_blob->blob.length;
	}
	if (challenge_blob != NULL) {
		request.data.ccache_ntlm_auth.challenge_blob_len =
			challenge_blob->blob.length;
		request.extra_len += challenge_blob->blob.length;
	}

	if (request.extra_len != 0) {
		request.extra_data.data = (char *)malloc(request.extra_len);
		if (request.extra_data.data == NULL) {
			status = WBC_ERR_NO_MEMORY;
			goto fail;
		}
	}
	if (initial_blob != NULL) {
		memcpy(request.extra_data.data,
		       initial_blob->blob.data, initial_blob->blob.length);
	}
	if (challenge_blob != NULL) {
		memcpy(request.extra_data.data
		       + request.data.ccache_ntlm_auth.initial_blob_len,
		       challenge_blob->blob.data,
		       challenge_blob->blob.length);
	}

	status = wbcRequestResponse(ctx, WINBINDD_CCACHE_NTLMAUTH,
				    &request, &response);
	if (!WBC_ERROR_IS_OK(status)) {
		goto fail;
	}

	result = (struct wbcCredentialCacheInfo *)wbcAllocateMemory(
		1, sizeof(struct wbcCredentialCacheInfo),
		wbcCredentialCacheInfoDestructor);
	if (result == NULL) {
		status = WBC_ERR_NO_MEMORY;
		goto fail;
	}
	result->num_blobs = 0;
	result->blobs = NULL;
	status = wbcAddNamedBlob(&result->num_blobs, &result->blobs,
				 "auth_blob", 0,
				 (uint8_t *)response.extra_data.data,
				 response.data.ccache_ntlm_auth.auth_blob_len);
	if (!WBC_ERROR_IS_OK(status)) {
		goto fail;
	}
	status = wbcAddNamedBlob(
		&result->num_blobs, &result->blobs, "session_key", 0,
		response.data.ccache_ntlm_auth.session_key,
		sizeof(response.data.ccache_ntlm_auth.session_key));
	if (!WBC_ERROR_IS_OK(status)) {
		goto fail;
	}
	if (response.data.ccache_ntlm_auth.new_spnego) {
		status = wbcAddNamedBlob(
			&result->num_blobs, &result->blobs, "new_spnego", 0,
			&response.data.ccache_ntlm_auth.new_spnego,
			sizeof(response.data.ccache_ntlm_auth.new_spnego));
		if (!WBC_ERROR_IS_OK(status)) {
			goto fail;
		}
	}

	*info = result;
	result = NULL;
	status = WBC_ERR_SUCCESS;
fail:
	free(request.extra_data.data);
	winbindd_free_response(&response);
	wbcFreeMemory(result);
	return status;
}
Exemple #19
0
wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
{
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	struct wbcInterfaceDetails *info;
	struct wbcDomainInfo *domain = NULL;
	struct winbindd_request request;
	struct winbindd_response response;

	/* Initialize request */

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	info = (struct wbcInterfaceDetails *)wbcAllocateMemory(
		1, sizeof(struct wbcInterfaceDetails),
		wbcInterfaceDetailsDestructor);
	BAIL_ON_PTR_ERROR(info, wbc_status);

	/* first the interface version */
	wbc_status = wbcRequestResponse(WINBINDD_INTERFACE_VERSION, NULL, &response);
	BAIL_ON_WBC_ERROR(wbc_status);
	info->interface_version = response.data.interface_version;

	/* then the samba version and the winbind separator */
	wbc_status = wbcRequestResponse(WINBINDD_INFO, NULL, &response);
	BAIL_ON_WBC_ERROR(wbc_status);

	info->winbind_version = strdup(response.data.info.samba_version);
	BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status);
	info->winbind_separator = response.data.info.winbind_separator;

	/* then the local netbios name */
	wbc_status = wbcRequestResponse(WINBINDD_NETBIOS_NAME, NULL, &response);
	BAIL_ON_WBC_ERROR(wbc_status);

	info->netbios_name = strdup(response.data.netbios_name);
	BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status);

	/* then the local workgroup name */
	wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_NAME, NULL, &response);
	BAIL_ON_WBC_ERROR(wbc_status);

	info->netbios_domain = strdup(response.data.domain_name);
	BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status);

	wbc_status = wbcDomainInfo(info->netbios_domain, &domain);
	if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
		/* maybe it's a standalone server */
		domain = NULL;
		wbc_status = WBC_ERR_SUCCESS;
	} else {
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	if (domain) {
		info->dns_domain = strdup(domain->dns_name);
		wbcFreeMemory(domain);
		BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status);
	} else {
		info->dns_domain = NULL;
	}

	*_details = info;
	info = NULL;

	wbc_status = WBC_ERR_SUCCESS;

done:
	wbcFreeMemory(info);
	return wbc_status;
}