Пример #1
0
/* take a group id and return a filled struct group */
static struct group *wb_aix_getgrgid(gid_t gid)
{
	struct winbindd_response response;
	struct winbindd_request request;
	struct group *grp;
	NSS_STATUS ret;

	logit("getgrgid %d\n", gid);

	ZERO_STRUCT(response);
	ZERO_STRUCT(request);

	request.data.gid = gid;

	ret = winbindd_request_response(NULL, WINBINDD_GETGRGID,
					&request, &response);

	logit("getgrgid ret=%d\n", ret);

	HANDLE_ERRORS(ret);

	grp = fill_grent(&response.data.gr, response.extra_data.data);

	winbindd_free_response(&response);

	return grp;
}
Пример #2
0
/* take a username and return a filled struct passwd */
static struct passwd *wb_aix_getpwnam(const char *name)
{
	struct winbindd_response response;
	struct winbindd_request request;
	NSS_STATUS ret;
	struct passwd *pwd;

	if (*name == WB_AIX_ENCODED) {
		return wb_aix_getpwuid(decode_id(name));
	}

	logit("getpwnam '%s'\n", name);

	ZERO_STRUCT(response);
	ZERO_STRUCT(request);

	STRCPY_RETNULL(request.data.username, name);

	ret = winbindd_request_response(NULL, WINBINDD_GETPWNAM,
					&request, &response);

	HANDLE_ERRORS(ret);

	pwd = fill_pwent(&response.data.pw);

	winbindd_free_response(&response);

	logit("getpwnam gave ptr %p\n", pwd);

	return pwd;
}
Пример #3
0
/* take a group name and return a filled struct group */
static struct group *wb_aix_getgrnam(const char *name)
{
	struct winbindd_response response;
	struct winbindd_request request;
	NSS_STATUS ret;
	struct group *grp;

	if (*name == WB_AIX_ENCODED) {
		return wb_aix_getgrgid(decode_id(name));
	}

	logit("getgrnam '%s'\n", name);

	ZERO_STRUCT(response);
	ZERO_STRUCT(request);

	STRCPY_RETNULL(request.data.groupname, name);

	ret = winbindd_request_response(NULL, WINBINDD_GETGRNAM,
					&request, &response);

	HANDLE_ERRORS(ret);

	grp = fill_grent(&response.data.gr, response.extra_data.data);

	winbindd_free_response(&response);

	return grp;
}
Пример #4
0
/* take a uid and return a filled struct passwd */
static struct passwd *wb_aix_getpwuid(uid_t uid)
{
	struct winbindd_response response;
	struct winbindd_request request;
	NSS_STATUS ret;
	struct passwd *pwd;

	logit("getpwuid '%d'\n", uid);

	ZERO_STRUCT(response);
	ZERO_STRUCT(request);

	request.data.uid = uid;

	ret = winbindd_request_response(NULL, WINBINDD_GETPWUID,
					&request, &response);

	HANDLE_ERRORS(ret);

	pwd = fill_pwent(&response.data.pw);

	winbindd_free_response(&response);

	logit("getpwuid gave ptr %p\n", pwd);

	return pwd;
}
Пример #5
0
NSS_STATUS
_nss_winbind_endgrent(void)
{
	NSS_STATUS ret;
#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: endgrent\n", getpid());
#endif

#if HAVE_PTHREAD
	pthread_mutex_lock(&winbind_nss_mutex);
#endif

	if (num_gr_cache > 0) {
		ndx_gr_cache = num_gr_cache = 0;
		winbindd_free_response(&getgrent_response);
	}

	ret = winbindd_request_response(NULL, WINBINDD_ENDGRENT, NULL, NULL);
#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(),
		nss_err_str(ret), ret);
#endif

#if HAVE_PTHREAD
	pthread_mutex_unlock(&winbind_nss_mutex);
#endif

	return ret;
}
Пример #6
0
NSS_STATUS winbindd_get_response(struct winbindd_response *response)
{
	struct winbindd_response lresponse;

	if (!response) {
		ZERO_STRUCT(lresponse);
		response = &lresponse;
	}

	init_response(response);

	/* Wait for reply */
	if (winbindd_read_reply(response) == -1) {
		/* Set ENOENT for consistency.  Required by some apps */
		errno = ENOENT;

		return NSS_STATUS_UNAVAIL;
	}

	/* Throw away extra data if client didn't request it */
	if (response == &lresponse) {
		winbindd_free_response(response);
	}

	/* Copy reply data from socket */
	if (response->result != WINBINDD_OK) {
		return NSS_STATUS_NOTFOUND;
	}

	return NSS_STATUS_SUCCESS;
}
Пример #7
0
/*
  list groups
*/
static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
{
	NSS_STATUS ret;
	struct winbindd_request request;
	struct winbindd_response response;
	int len;
	char *s;

	if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
		logit("invalid lsgroup op\n");
		errno = EINVAL;
		return -1;
	}

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	ret = winbindd_request_response(NULL, WINBINDD_LIST_GROUPS,
					&request, &response);
	if (ret != 0) {
		errno = EINVAL;
		return -1;
	}

	len = strlen(response.extra_data.data);

	s = malloc(len+2);
	if (!s) {
		winbindd_free_response(&response);
		errno = ENOMEM;
		return -1;
	}

	memcpy(s, response.extra_data.data, len+1);

	replace_commas(s);

	results[0].attr_un.au_char = s;
	results[0].attr_flag = 0;

	winbindd_free_response(&response);

	return 0;
}
Пример #8
0
/* take a username and return a string containing a comma-separated
   list of group id numbers to which the user belongs */
static char *wb_aix_getgrset(char *user)
{
	struct winbindd_response response;
	struct winbindd_request request;
	NSS_STATUS ret;
	int i, idx;
	char *tmpbuf;
	int num_gids;
	gid_t *gid_list;
	char *r_user = user;

	if (*user == WB_AIX_ENCODED) {
		r_user = decode_user(r_user);
		if (!r_user) {
			errno = ENOENT;
			return NULL;
		}
	}

	logit("getgrset '%s'\n", r_user);

        ZERO_STRUCT(response);
        ZERO_STRUCT(request);

	STRCPY_RETNULL(request.data.username, r_user);

	if (*user == WB_AIX_ENCODED) {
		free(r_user);
	}

	ret = winbindd_request_response(NULL, WINBINDD_GETGROUPS,
					&request, &response);

	HANDLE_ERRORS(ret);

	num_gids = response.data.num_entries;
	gid_list = (gid_t *)response.extra_data.data;

	/* allocate a space large enough to contruct the string */
	tmpbuf = malloc(num_gids*12);
	if (!tmpbuf) {
		return NULL;
	}

	for (idx=i=0; i < num_gids-1; i++) {
		idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]);
	}
	idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);

	winbindd_free_response(&response);

	return tmpbuf;
}
Пример #9
0
static int winbindd_read_reply(struct winbindd_response *response)
{
	int result1, result2 = 0;

	if (!response) {
		return -1;
	}

	/* Read fixed length response */

	result1 = winbind_read_sock(response,
				    sizeof(struct winbindd_response));

	/* We actually send the pointer value of the extra_data field from
	   the server.  This has no meaning in the client's address space
	   so we clear it out. */

	response->extra_data.data = NULL;

	if (result1 == -1) {
		return -1;
	}

	if (response->length < sizeof(struct winbindd_response)) {
		return -1;
	}

	/* Read variable length response */

	if (response->length > sizeof(struct winbindd_response)) {
		int extra_data_len = response->length -
			sizeof(struct winbindd_response);

		/* Mallocate memory for extra data */

		if (!(response->extra_data.data = malloc(extra_data_len))) {
			return -1;
		}

		result2 = winbind_read_sock(response->extra_data.data,
					    extra_data_len);
		if (result2 == -1) {
			winbindd_free_response(response);
			return -1;
		}
	}

	/* Return total amount of data read */

	return result1 + result2;
}
Пример #10
0
/* return a list of group SIDs for a user SID */
NSS_STATUS
_nss_winbind_getusersids(const char *user_sid, char **group_sids,
			 int *num_groups,
			 char *buffer, size_t buf_size, int *errnop)
{
	NSS_STATUS ret;
	struct winbindd_request request;
	struct winbindd_response response;

#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid);
#endif

#if HAVE_PTHREAD
	pthread_mutex_lock(&winbind_nss_mutex);
#endif

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1);
	request.data.sid[sizeof(request.data.sid) - 1] = '\0';

	ret = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response);

	if (ret != NSS_STATUS_SUCCESS) {
		goto done;
	}

	if (buf_size < response.length - sizeof(response)) {
		ret = NSS_STATUS_TRYAGAIN;
		errno = *errnop = ERANGE;
		goto done;
	}

	*num_groups = response.data.num_entries;
	*group_sids = buffer;
	memcpy(buffer, response.extra_data.data, response.length - sizeof(response));
	errno = *errnop = 0;

 done:
	winbindd_free_response(&response);

#if HAVE_PTHREAD
	pthread_mutex_unlock(&winbind_nss_mutex);
#endif

	return ret;
}
Пример #11
0
/* map a user or group name to a SID string */
NSS_STATUS
_nss_winbind_nametosid(const char *name, char **sid, char *buffer,
		       size_t buflen, int *errnop)
{
	NSS_STATUS ret;
	struct winbindd_response response;
	struct winbindd_request request;

#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name);
#endif

#if HAVE_PTHREAD
	pthread_mutex_lock(&winbind_nss_mutex);
#endif

	ZERO_STRUCT(response);
	ZERO_STRUCT(request);

	strncpy(request.data.name.name, name,
		sizeof(request.data.name.name) - 1);
	request.data.name.name[sizeof(request.data.name.name) - 1] = '\0';

	ret = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
	if (ret != NSS_STATUS_SUCCESS) {
		*errnop = errno = EINVAL;
		goto failed;
	}

	if (buflen < strlen(response.data.sid.sid)+1) {
		ret = NSS_STATUS_TRYAGAIN;
		*errnop = errno = ERANGE;
		goto failed;
	}

	*errnop = errno = 0;
	*sid = buffer;
	strcpy(*sid, response.data.sid.sid);

failed:
	winbindd_free_response(&response);

#if HAVE_PTHREAD
	pthread_mutex_unlock(&winbind_nss_mutex);
#endif

	return ret;
}
Пример #12
0
/* map a gid to a SID string */
NSS_STATUS
_nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer,
		      size_t buflen, int *errnop)
{
	NSS_STATUS ret;
	struct winbindd_response response;
	struct winbindd_request request;

#ifdef DEBUG_NSS
	fprintf(stderr, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid);
#endif

#if HAVE_PTHREAD
	pthread_mutex_lock(&winbind_nss_mutex);
#endif

	ZERO_STRUCT(response);
	ZERO_STRUCT(request);

	request.data.gid = gid;

	ret = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response);
	if (ret != NSS_STATUS_SUCCESS) {
		*errnop = errno = EINVAL;
		goto failed;
	}

	if (buflen < strlen(response.data.sid.sid)+1) {
		ret = NSS_STATUS_TRYAGAIN;
		*errnop = errno = ERANGE;
		goto failed;
	}

	*errnop = errno = 0;
	*sid = buffer;
	strcpy(*sid, response.data.sid.sid);

failed:
	winbindd_free_response(&response);

#if HAVE_PTHREAD
	pthread_mutex_unlock(&winbind_nss_mutex);
#endif

	return ret;
}
Пример #13
0
/*
  authenticate a user
 */
static int wb_aix_authenticate(char *user, char *pass,
			       int *reenter, char **message)
{
	struct winbindd_request request;
	struct winbindd_response response;
        NSS_STATUS result;
	char *r_user = user;

	logit("authenticate '%s' response='%s'\n", user, pass);

	*reenter = 0;
	*message = NULL;

	/* Send off request */
	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	if (*user == WB_AIX_ENCODED) {
		r_user = decode_user(r_user);
		if (!r_user) {
			return AUTH_NOTFOUND;
		}
	}

	STRCPY_RET(request.data.auth.user, r_user);
	STRCPY_RET(request.data.auth.pass, pass);

	if (*user == WB_AIX_ENCODED) {
		free(r_user);
	}

	result = winbindd_request_response(NULL, WINBINDD_PAM_AUTH,
					   &request, &response);

	winbindd_free_response(&response);

	logit("auth result %d for '%s'\n", result, user);

	if (result == NSS_STATUS_SUCCESS) {
		errno = 0;
		return AUTH_SUCCESS;
	}

	return AUTH_FAILURE;
}
Пример #14
0
/*
  change a user password
*/
static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message)
{
	struct winbindd_request request;
	struct winbindd_response response;
        NSS_STATUS result;
	char *r_user = user;

	if (*user == WB_AIX_ENCODED) {
		r_user = decode_user(r_user);
		if (!r_user) {
			errno = ENOENT;
			return -1;
		}
	}

	logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);

	*message = NULL;

	/* Send off request */
	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	STRCPY_RET(request.data.chauthtok.user, r_user);
	STRCPY_RET(request.data.chauthtok.oldpass, oldpass);
	STRCPY_RET(request.data.chauthtok.newpass, newpass);

	if (*user == WB_AIX_ENCODED) {
		free(r_user);
	}

	result = winbindd_request_response(NULL, WINBINDD_PAM_CHAUTHTOK,
					   &request, &response);

	winbindd_free_response(&response);

	if (result == NSS_STATUS_SUCCESS) {
		errno = 0;
		return 0;
	}

	errno = EINVAL;
	return -1;
}
static NSS_STATUS
_nss_winbind_ipnodes_getbyname(nss_backend_t* be, void *args)
{
	nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
	struct winbindd_response response;
	struct winbindd_request request;
	NSS_STATUS ret;
	int af;

	ZERO_STRUCT(response);
	ZERO_STRUCT(request);

	/* I assume there that AI_ADDRCONFIG cases are handled in nss
	   frontend code, at least it seems done so in solaris...

	   we will give NO_DATA for pure IPv6; IPv4 will be returned for
	   AF_INET or for AF_INET6 and AI_ALL|AI_V4MAPPED we have to map
	   IPv4 to IPv6.
	 */
#if defined(AF_INET6)
#ifdef HAVE_NSS_XBYY_KEY_IPNODE
	af = argp->key.ipnode.af_family;
	if(af == AF_INET6 && argp->key.ipnode.flags == 0) {
		argp->h_errno = NO_DATA;
		return NSS_STATUS_UNAVAIL;
	}
#else
	/* I'm not that sure if this is correct, but... */
	af = AF_INET6;
#endif
#endif

	strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1);
	request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0';

	if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response))
		== NSS_STATUS_SUCCESS ) {
	  ret = parse_response(af, argp, &response);
	}

	winbindd_free_response(&response);
	return ret;
}
static NSS_STATUS
_nss_winbind_hosts_getbyname(nss_backend_t* be, void *args)
{
	nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
	struct winbindd_response response;
	struct winbindd_request request;
	NSS_STATUS ret;

	ZERO_STRUCT(response);
	ZERO_STRUCT(request);
	
	strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1);
	request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0';

	if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response))
		== NSS_STATUS_SUCCESS ) {
	  ret = parse_response(AF_INET, argp, &response);
	}

	winbindd_free_response(&response);
	return ret;
}
static NSS_STATUS
_nss_winbind_hosts_getbyaddr(nss_backend_t* be, void *args)
{
	NSS_STATUS ret;
	struct winbindd_response response;
	struct winbindd_request request;
	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)args;
	const char *p;

	ZERO_STRUCT(response);
	ZERO_STRUCT(request);

#if defined(AF_INET6)
	/* winbindd currently does not resolve IPv6 */
	if(argp->key.hostaddr.type == AF_INET6) {
		argp->h_errno = NO_DATA;
		return NSS_STATUS_UNAVAIL;
	}

	p = inet_ntop(argp->key.hostaddr.type, argp->key.hostaddr.addr,
			request.data.winsreq, sizeof request.data.winsreq);
#else
        snprintf(request.data.winsreq, sizeof request.data.winsreq,
                "%u.%u.%u.%u", 
                ((unsigned char *)argp->key.hostaddr.addr)[0],
                ((unsigned char *)argp->key.hostaddr.addr)[1],
                ((unsigned char *)argp->key.hostaddr.addr)[2],
                ((unsigned char *)argp->key.hostaddr.addr)[3]);
#endif

	ret = winbindd_request_response(WINBINDD_WINS_BYIP, &request, &response);

	if( ret == NSS_STATUS_SUCCESS) {
	  parse_response(argp->key.hostaddr.type, argp, &response);
	}
	winbindd_free_response(&response);
        return ret;
}
Пример #18
0
NSS_STATUS
_nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
			size_t buflen, int *errnop)
{
	NSS_STATUS ret;
	static struct winbindd_response response;
	struct winbindd_request request;
	static int keep_response;

#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getpwuid_r %d\n", getpid(), (unsigned int)uid);
#endif

#if HAVE_PTHREAD
	pthread_mutex_lock(&winbind_nss_mutex);
#endif

	/* If our static buffer needs to be expanded we are called again */
	if (!keep_response || uid != response.data.pw.pw_uid) {

		/* Call for the first time */

		ZERO_STRUCT(response);
		ZERO_STRUCT(request);

		request.data.uid = uid;

		ret = winbindd_request_response(NULL, WINBINDD_GETPWUID, &request, &response);

		if (ret == NSS_STATUS_SUCCESS) {
			ret = fill_pwent(result, &response.data.pw,
					 &buffer, &buflen);

			if (ret == NSS_STATUS_TRYAGAIN) {
				keep_response = true;
				*errnop = errno = ERANGE;
				goto done;
			}
		}

	} else {

		/* We've been called again */

		ret = fill_pwent(result, &response.data.pw, &buffer, &buflen);

		if (ret == NSS_STATUS_TRYAGAIN) {
			*errnop = errno = ERANGE;
			goto done;
		}

		keep_response = false;
		*errnop = errno = 0;
	}

	winbindd_free_response(&response);

	done:

#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),
		(unsigned int)uid, nss_err_str(ret), ret);
#endif

#if HAVE_PTHREAD
	pthread_mutex_unlock(&winbind_nss_mutex);
#endif

	return ret;
}
Пример #19
0
/* Logon a User */
wbcErr wbcCtxLogonUser(struct wbcContext *ctx,
		       const struct wbcLogonUserParams *params,
		       struct wbcLogonUserInfo **info,
		       struct wbcAuthErrorInfo **error,
		       struct wbcUserPasswordPolicyInfo **policy)
{
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	struct winbindd_request request;
	struct winbindd_response response;
	uint32_t i;

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	if (info) {
		*info = NULL;
	}
	if (error) {
		*error = NULL;
	}
	if (policy) {
		*policy = NULL;
	}

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

	if (!params->username) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	if ((params->num_blobs > 0) && (params->blobs == NULL)) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}
	if ((params->num_blobs == 0) && (params->blobs != NULL)) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	/* Initialize request */

	request.flags = WBFLAG_PAM_INFO3_TEXT |
			WBFLAG_PAM_USER_SESSION_KEY |
			WBFLAG_PAM_LMKEY;

	if (!params->password) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	strncpy(request.data.auth.user,
		params->username,
		sizeof(request.data.auth.user)-1);

	strncpy(request.data.auth.pass,
		params->password,
		sizeof(request.data.auth.pass)-1);

	for (i=0; i<params->num_blobs; i++) {

		if (strcasecmp(params->blobs[i].name, "krb5_cc_type") == 0) {
			if (params->blobs[i].blob.data) {
				strncpy(request.data.auth.krb5_cc_type,
					(const char *)params->blobs[i].blob.data,
					sizeof(request.data.auth.krb5_cc_type) - 1);
			}
			continue;
		}

		if (strcasecmp(params->blobs[i].name, "user_uid") == 0) {
			if (params->blobs[i].blob.data) {
				memcpy(&request.data.auth.uid,
					params->blobs[i].blob.data,
					MIN(sizeof(request.data.auth.uid),
					    params->blobs[i].blob.length));
			}
			continue;
		}

		if (strcasecmp(params->blobs[i].name, "flags") == 0) {
			if (params->blobs[i].blob.data) {
				uint32_t flags;
				memcpy(&flags,
					params->blobs[i].blob.data,
					MIN(sizeof(flags),
					    params->blobs[i].blob.length));
				request.flags |= flags;
			}
			continue;
		}

		if (strcasecmp(params->blobs[i].name, "membership_of") == 0) {
			if (params->blobs[i].blob.data &&
			    params->blobs[i].blob.data[0] > 0) {
				strncpy(request.data.auth.require_membership_of_sid,
					(const char *)params->blobs[i].blob.data,
					sizeof(request.data.auth.require_membership_of_sid) - 1);
			}
			continue;
		}
	}

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

	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);

	if (info) {
		wbc_status = wbc_create_logon_info(&response,
						   info);
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	if (policy) {
		wbc_status = wbc_create_password_policy_info(&response,
							     policy);
		BAIL_ON_WBC_ERROR(wbc_status);
	}

done:
	winbindd_free_response(&response);

	return wbc_status;
}
Пример #20
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;
}
Пример #21
0
/* Authenticate with more detailed information */
wbcErr wbcCtxAuthenticateUserEx(struct wbcContext *ctx,
				const struct wbcAuthUserParams *params,
				struct wbcAuthUserInfo **info,
				struct wbcAuthErrorInfo **error)
{
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	int cmd = 0;
	struct winbindd_request request;
	struct winbindd_response response;

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	if (error) {
		*error = NULL;
	}

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

	if (params->level != WBC_AUTH_USER_LEVEL_PAC && !params->account_name) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	/* Initialize request */

	switch (params->level) {
	case WBC_AUTH_USER_LEVEL_PLAIN:
		cmd = WINBINDD_PAM_AUTH;
		request.flags = WBFLAG_PAM_INFO3_TEXT |
				WBFLAG_PAM_USER_SESSION_KEY |
				WBFLAG_PAM_LMKEY;

		if (!params->password.plaintext) {
			wbc_status = WBC_ERR_INVALID_PARAM;
			BAIL_ON_WBC_ERROR(wbc_status);
		}

		if (params->domain_name && params->domain_name[0]) {
			/* We need to get the winbind separator :-( */
			struct winbindd_response sep_response;

			ZERO_STRUCT(sep_response);

			wbc_status = wbcRequestResponse(ctx, WINBINDD_INFO,
							NULL, &sep_response);
			BAIL_ON_WBC_ERROR(wbc_status);

			snprintf(request.data.auth.user,
				 sizeof(request.data.auth.user)-1,
				 "%s%c%s",
				 params->domain_name,
				 sep_response.data.info.winbind_separator,
				 params->account_name);
		} else {
			strncpy(request.data.auth.user,
				params->account_name,
				sizeof(request.data.auth.user)-1);
		}

		strncpy(request.data.auth.pass,
			params->password.plaintext,
			sizeof(request.data.auth.pass)-1);
		break;

	case WBC_AUTH_USER_LEVEL_HASH:
		wbc_status = WBC_ERR_NOT_IMPLEMENTED;
		BAIL_ON_WBC_ERROR(wbc_status);
		break;

	case WBC_AUTH_USER_LEVEL_RESPONSE:
		cmd = WINBINDD_PAM_AUTH_CRAP;
		request.flags = WBFLAG_PAM_INFO3_TEXT |
				WBFLAG_PAM_USER_SESSION_KEY |
				WBFLAG_PAM_LMKEY;

		if (params->password.response.lm_length &&
		    !params->password.response.lm_data) {
			wbc_status = WBC_ERR_INVALID_PARAM;
			BAIL_ON_WBC_ERROR(wbc_status);
		}
		if (params->password.response.lm_length == 0 &&
		    params->password.response.lm_data) {
			wbc_status = WBC_ERR_INVALID_PARAM;
			BAIL_ON_WBC_ERROR(wbc_status);
		}

		if (params->password.response.nt_length &&
		    !params->password.response.nt_data) {
			wbc_status = WBC_ERR_INVALID_PARAM;
			BAIL_ON_WBC_ERROR(wbc_status);
		}
		if (params->password.response.nt_length == 0&&
		    params->password.response.nt_data) {
			wbc_status = WBC_ERR_INVALID_PARAM;
			BAIL_ON_WBC_ERROR(wbc_status);
		}

		strncpy(request.data.auth_crap.user,
			params->account_name,
			sizeof(request.data.auth_crap.user)-1);
		if (params->domain_name) {
			strncpy(request.data.auth_crap.domain,
				params->domain_name,
				sizeof(request.data.auth_crap.domain)-1);
		}
		if (params->workstation_name) {
			strncpy(request.data.auth_crap.workstation,
				params->workstation_name,
				sizeof(request.data.auth_crap.workstation)-1);
		}

		request.data.auth_crap.logon_parameters =
				params->parameter_control;

		memcpy(request.data.auth_crap.chal,
		       params->password.response.challenge,
		       sizeof(request.data.auth_crap.chal));

		request.data.auth_crap.lm_resp_len =
				MIN(params->password.response.lm_length,
				    sizeof(request.data.auth_crap.lm_resp));
		if (params->password.response.lm_data) {
			memcpy(request.data.auth_crap.lm_resp,
			       params->password.response.lm_data,
			       request.data.auth_crap.lm_resp_len);
		}
		request.data.auth_crap.nt_resp_len = params->password.response.nt_length;
		if (params->password.response.nt_length > sizeof(request.data.auth_crap.nt_resp)) {
			request.flags |= WBFLAG_BIG_NTLMV2_BLOB;
			request.extra_len = params->password.response.nt_length;
			request.extra_data.data = (char *)malloc(
				request.extra_len);
			if (request.extra_data.data == NULL) {
				wbc_status = WBC_ERR_NO_MEMORY;
				BAIL_ON_WBC_ERROR(wbc_status);
			}
			memcpy(request.extra_data.data,
			       params->password.response.nt_data,
			       request.data.auth_crap.nt_resp_len);
		} else if (params->password.response.nt_data) {
			memcpy(request.data.auth_crap.nt_resp,
			       params->password.response.nt_data,
			       request.data.auth_crap.nt_resp_len);
		}
		break;

	case WBC_AUTH_USER_LEVEL_PAC:
		cmd = WINBINDD_PAM_AUTH_CRAP;
		request.flags = WBFLAG_PAM_AUTH_PAC | WBFLAG_PAM_INFO3_TEXT;
		request.extra_data.data = malloc(params->password.pac.length);
		if (request.extra_data.data == NULL) {
			wbc_status = WBC_ERR_NO_MEMORY;
			BAIL_ON_WBC_ERROR(wbc_status);
		}
		memcpy(request.extra_data.data, params->password.pac.data,
		       params->password.pac.length);
		request.extra_len = params->password.pac.length;
		break;

	default:
		break;
	}

	if (cmd == 0) {
		wbc_status = WBC_ERR_INVALID_PARAM;
		BAIL_ON_WBC_ERROR(wbc_status);
	}

	if (params->flags) {
		request.flags |= params->flags;
	}

	if (cmd == WINBINDD_PAM_AUTH_CRAP) {
		wbc_status = wbcRequestResponsePriv(ctx, cmd,
						    &request, &response);
	} else {
		wbc_status = wbcRequestResponse(ctx, cmd,
						&request, &response);
	}
	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);

	if (info) {
		wbc_status = wbc_create_auth_info(&response, info);
		BAIL_ON_WBC_ERROR(wbc_status);
	}

done:
	winbindd_free_response(&response);

	free(request.extra_data.data);

	return wbc_status;
}
Пример #22
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;
}
Пример #23
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;
}
Пример #24
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;
}
Пример #25
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;
}
Пример #26
0
/* Lists Groups */
wbcErr wbcListGroups(const char *domain_name,
		     uint32_t *_num_groups,
		     const char ***_groups)
{
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	struct winbindd_request request;
	struct winbindd_response response;
	uint32_t num_groups = 0;
	const char **groups = NULL;
	const char *next;

	/* Initialise request */

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

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

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

	groups = wbcAllocateStringArray(response.data.num_entries);
	if (groups == NULL) {
		return WBC_ERR_NO_MEMORY;
	}

	/* Look through extra data */

	next = (const char *)response.extra_data.data;
	while (next) {
		const char *current;
		char *k;

		if (num_groups >= response.data.num_entries) {
			wbc_status = WBC_ERR_INVALID_RESPONSE;
			goto done;
		}

		current = next;
		k = strchr(next, ',');

		if (k) {
			k[0] = '\0';
			next = k+1;
		} else {
			next = NULL;
		}

		groups[num_groups] = strdup(current);
		BAIL_ON_PTR_ERROR(groups[num_groups], wbc_status);
		num_groups += 1;
	}
	if (num_groups != response.data.num_entries) {
		wbc_status = WBC_ERR_INVALID_RESPONSE;
		goto done;
	}

	*_num_groups = response.data.num_entries;
	*_groups = groups;
	groups = NULL;
	wbc_status = WBC_ERR_SUCCESS;

 done:
	winbindd_free_response(&response);
	wbcFreeMemory(groups);
	return wbc_status;
}
Пример #27
0
NSS_STATUS
_nss_winbind_getgrgid_r(gid_t gid,
			struct group *result, char *buffer,
			size_t buflen, int *errnop)
{
	NSS_STATUS ret;
	static struct winbindd_response response;
	struct winbindd_request request;
	static int keep_response;

#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid);
#endif

#if HAVE_PTHREAD
	pthread_mutex_lock(&winbind_nss_mutex);
#endif

	/* If our static buffer needs to be expanded we are called again */
	/* Or if the stored response group name differs from the request. */

	if (!keep_response || gid != response.data.gr.gr_gid) {

		/* Call for the first time */

		ZERO_STRUCT(request);
		ZERO_STRUCT(response);

		request.data.gid = gid;

		ret = winbindd_request_response(NULL, WINBINDD_GETGRGID,
						&request, &response);

		if (ret == NSS_STATUS_SUCCESS) {

			ret = fill_grent(result, &response.data.gr,
					 (char *)response.extra_data.data,
					 &buffer, &buflen);

			if (ret == NSS_STATUS_TRYAGAIN) {
				keep_response = true;
				*errnop = errno = ERANGE;
				goto done;
			}
		}

	} else {

		/* We've been called again */

		ret = fill_grent(result, &response.data.gr,
				 (char *)response.extra_data.data, &buffer,
				 &buflen);

		if (ret == NSS_STATUS_TRYAGAIN) {
			keep_response = true;
			*errnop = errno = ERANGE;
			goto done;
		}

		keep_response = false;
		*errnop = 0;
	}

	winbindd_free_response(&response);
	done:
#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(),
		(unsigned int)gid, nss_err_str(ret), ret);
#endif

#if HAVE_PTHREAD
	pthread_mutex_unlock(&winbind_nss_mutex);
#endif
	return ret;
}
Пример #28
0
static NSS_STATUS
winbind_getgrent(enum winbindd_cmd cmd,
		 struct group *result,
		 char *buffer, size_t buflen, int *errnop)
{
	NSS_STATUS ret;
	static struct winbindd_request request;
	static int called_again;


#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getgrent\n", getpid());
#endif

#if HAVE_PTHREAD
	pthread_mutex_lock(&winbind_nss_mutex);
#endif

	/* Return an entry from the cache if we have one, or if we are
	   called again because we exceeded our static buffer.  */

	if ((ndx_gr_cache < num_gr_cache) || called_again) {
		goto return_result;
	}

	/* Else call winbindd to get a bunch of entries */

	if (num_gr_cache > 0) {
		winbindd_free_response(&getgrent_response);
	}

	ZERO_STRUCT(request);
	ZERO_STRUCT(getgrent_response);

	request.data.num_entries = MAX_GETGRENT_USERS;

	ret = winbindd_request_response(NULL, cmd, &request,
			       &getgrent_response);

	if (ret == NSS_STATUS_SUCCESS) {
		struct winbindd_gr *gr_cache;
		int mem_ofs;

		/* Fill cache */

		ndx_gr_cache = 0;
		num_gr_cache = getgrent_response.data.num_entries;

		/* Return a result */

	return_result:

		gr_cache = (struct winbindd_gr *)
			getgrent_response.extra_data.data;

		/* Check data is valid */

		if (gr_cache == NULL) {
			ret = NSS_STATUS_NOTFOUND;
			goto done;
		}

		/* Fill group membership.  The offset into the extra data
		   for the group membership is the reported offset plus the
		   size of all the winbindd_gr records returned. */

		mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs +
			num_gr_cache * sizeof(struct winbindd_gr);

		ret = fill_grent(result, &gr_cache[ndx_gr_cache],
				 ((char *)getgrent_response.extra_data.data)+mem_ofs,
				 &buffer, &buflen);

		/* Out of memory - try again */

		if (ret == NSS_STATUS_TRYAGAIN) {
			called_again = true;
			*errnop = errno = ERANGE;
			goto done;
		}

		*errnop = 0;
		called_again = false;
		ndx_gr_cache++;

		/* If we've finished with this lot of results free cache */

		if (ndx_gr_cache == num_gr_cache) {
			ndx_gr_cache = num_gr_cache = 0;
			winbindd_free_response(&getgrent_response);
		}
	}
	done:
#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(),
		nss_err_str(ret), ret);
#endif

#if HAVE_PTHREAD
	pthread_mutex_unlock(&winbind_nss_mutex);
#endif

	return ret;
}
Пример #29
0
NSS_STATUS
_nss_winbind_getpwent_r(struct passwd *result, char *buffer,
			size_t buflen, int *errnop)
{
	NSS_STATUS ret;
	struct winbindd_request request;
	static int called_again;

#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getpwent\n", getpid());
#endif

#if HAVE_PTHREAD
	pthread_mutex_lock(&winbind_nss_mutex);
#endif

	/* Return an entry from the cache if we have one, or if we are
	   called again because we exceeded our static buffer.  */

	if ((ndx_pw_cache < num_pw_cache) || called_again) {
		goto return_result;
	}

	/* Else call winbindd to get a bunch of entries */

	if (num_pw_cache > 0) {
		winbindd_free_response(&getpwent_response);
	}

	ZERO_STRUCT(request);
	ZERO_STRUCT(getpwent_response);

	request.data.num_entries = MAX_GETPWENT_USERS;

	ret = winbindd_request_response(NULL, WINBINDD_GETPWENT, &request,
			       &getpwent_response);

	if (ret == NSS_STATUS_SUCCESS) {
		struct winbindd_pw *pw_cache;

		/* Fill cache */

		ndx_pw_cache = 0;
		num_pw_cache = getpwent_response.data.num_entries;

		/* Return a result */

	return_result:

		pw_cache = (struct winbindd_pw *)
			getpwent_response.extra_data.data;

		/* Check data is valid */

		if (pw_cache == NULL) {
			ret = NSS_STATUS_NOTFOUND;
			goto done;
		}

		ret = fill_pwent(result, &pw_cache[ndx_pw_cache],
				 &buffer, &buflen);

		/* Out of memory - try again */

		if (ret == NSS_STATUS_TRYAGAIN) {
			called_again = true;
			*errnop = errno = ERANGE;
			goto done;
		}

		*errnop = errno = 0;
		called_again = false;
		ndx_pw_cache++;

		/* If we've finished with this lot of results free cache */

		if (ndx_pw_cache == num_pw_cache) {
			ndx_pw_cache = num_pw_cache = 0;
			winbindd_free_response(&getpwent_response);
		}
	}
	done:
#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(),
		nss_err_str(ret), ret);
#endif

#if HAVE_PTHREAD
	pthread_mutex_unlock(&winbind_nss_mutex);
#endif
	return ret;
}
Пример #30
0
/* Return passwd struct from username */
NSS_STATUS
_nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
			size_t buflen, int *errnop)
{
	NSS_STATUS ret;
	static struct winbindd_response response;
	struct winbindd_request request;
	static int keep_response;

#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getpwnam_r %s\n", getpid(), name);
#endif

#if HAVE_PTHREAD
	pthread_mutex_lock(&winbind_nss_mutex);
#endif

	/* If our static buffer needs to be expanded we are called again */

	if (!keep_response || strcmp(name,response.data.pw.pw_name) != 0) {

		/* Call for the first time */

		ZERO_STRUCT(response);
		ZERO_STRUCT(request);

		strncpy(request.data.username, name,
			sizeof(request.data.username) - 1);
		request.data.username
			[sizeof(request.data.username) - 1] = '\0';

		ret = winbindd_request_response(NULL, WINBINDD_GETPWNAM, &request, &response);

		if (ret == NSS_STATUS_SUCCESS) {
			ret = fill_pwent(result, &response.data.pw, &buffer,
					 &buflen);

			if (ret == NSS_STATUS_TRYAGAIN) {
				keep_response = true;
				*errnop = errno = ERANGE;
				goto done;
			}
		}

	} else {

		/* We've been called again */

		ret = fill_pwent(result, &response.data.pw, &buffer, &buflen);

		if (ret == NSS_STATUS_TRYAGAIN) {
			keep_response = true;
			*errnop = errno = ERANGE;
			goto done;
		}

		keep_response = false;
		*errnop = errno = 0;
	}

	winbindd_free_response(&response);
	done:
#ifdef DEBUG_NSS
	fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),
		name, nss_err_str(ret), ret);
#endif

#if HAVE_PTHREAD
	pthread_mutex_unlock(&winbind_nss_mutex);
#endif

	return ret;
}