Exemplo n.º 1
0
static int winbind_named_pipe_sock(const char *dir)
{
	struct sockaddr_un sunaddr;
	struct stat st;
	char *path = NULL;
	int fd;
	int wait_time;
	int slept;

	/* Check permissions on unix socket directory */

	if (lstat(dir, &st) == -1) {
		errno = ENOENT;
		return -1;
	}

	/*
	 * This tells us that the pipe is owned by a privileged
	 * process, as we will be sending passwords to it.
	 */
	if (!S_ISDIR(st.st_mode) ||
	    !winbind_privileged_pipe_is_root(st.st_uid)) {
		errno = ENOENT;
		return -1;
	}

	/* Connect to socket */

	if (asprintf(&path, "%s/%s", dir, WINBINDD_SOCKET_NAME) < 0) {
		return -1;
	}

	ZERO_STRUCT(sunaddr);
	sunaddr.sun_family = AF_UNIX;
	strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1);

	/* If socket file doesn't exist, don't bother trying to connect
	   with retry.  This is an attempt to make the system usable when
	   the winbindd daemon is not running. */

	if (lstat(path, &st) == -1) {
		errno = ENOENT;
		SAFE_FREE(path);
		return -1;
	}

	SAFE_FREE(path);
	/* Check permissions on unix socket file */

	/*
	 * This tells us that the pipe is owned by a privileged
	 * process, as we will be sending passwords to it.
	 */
	if (!S_ISSOCK(st.st_mode) ||
	    !winbind_privileged_pipe_is_root(st.st_uid)) {
		errno = ENOENT;
		return -1;
	}

	/* Connect to socket */

	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		return -1;
	}

	/* Set socket non-blocking and close on exec. */

	if ((fd = make_safe_fd( fd)) == -1) {
		return fd;
	}

	for (wait_time = 0; connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1;
			wait_time += slept) {
		struct pollfd pfd;
		int ret;
		int connect_errno = 0;
		socklen_t errnosize;

		if (wait_time >= CONNECT_TIMEOUT)
			goto error_out;

		switch (errno) {
			case EINPROGRESS:
				pfd.fd = fd;
				pfd.events = POLLOUT;

				ret = poll(&pfd, 1, (CONNECT_TIMEOUT - wait_time) * 1000);

				if (ret > 0) {
					errnosize = sizeof(connect_errno);

					ret = getsockopt(fd, SOL_SOCKET,
							SO_ERROR, &connect_errno, &errnosize);

					if (ret >= 0 && connect_errno == 0) {
						/* Connect succeed */
						goto out;
					}
				}

				slept = CONNECT_TIMEOUT;
				break;
			case EAGAIN:
				slept = rand() % 3 + 1;
				sleep(slept);
				break;
			default:
				goto error_out;
		}

	}

  out:

	return fd;

  error_out:

	close(fd);
	return -1;
}
Exemplo n.º 2
0
static int winbind_named_pipe_sock(const char *dir)
{
	OutputDebugString("Todo: winbind_named_pipe_sock\n");
#ifndef _XBOX
	struct sockaddr_un sunaddr;
	struct stat st;
	pstring path;
	int fd;
	int wait_time;
	int slept;
	
	/* Check permissions on unix socket directory */
	
	if (lstat(dir, &st) == -1) {
		return -1;
	}
	
	if (!S_ISDIR(st.st_mode) || 
	    (st.st_uid != 0 && st.st_uid != geteuid())) {
		return -1;
	}
	
	/* Connect to socket */
	
	strncpy(path, dir, sizeof(path) - 1);
	path[sizeof(path) - 1] = '\0';
	
	strncat(path, "/", sizeof(path) - 1 - strlen(path));
	path[sizeof(path) - 1] = '\0';
	
	strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1 - strlen(path));
	path[sizeof(path) - 1] = '\0';
	
	ZERO_STRUCT(sunaddr);
	sunaddr.sun_family = AF_UNIX;
	strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1);
	
	/* If socket file doesn't exist, don't bother trying to connect
	   with retry.  This is an attempt to make the system usable when
	   the winbindd daemon is not running. */

	if (lstat(path, &st) == -1) {
		return -1;
	}
	
	/* Check permissions on unix socket file */
	
	if (!S_ISSOCK(st.st_mode) || 
	    (st.st_uid != 0 && st.st_uid != geteuid())) {
		return -1;
	}
	
	/* Connect to socket */
	
	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		return -1;
	}

	/* Set socket non-blocking and close on exec. */

	if ((fd = make_safe_fd( fd)) == -1) {
		return fd;
	}

	for (wait_time = 0; connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1;
			wait_time += slept) {
		struct timeval tv;
		fd_set w_fds;
		int ret;
		int connect_errno = 0;
		socklen_t errnosize;

		if (wait_time >= CONNECT_TIMEOUT)
			goto error_out;

		switch (errno) {
			case EINPROGRESS:
				FD_ZERO(&w_fds);
				FD_SET(fd, &w_fds);
				tv.tv_sec = CONNECT_TIMEOUT - wait_time;
				tv.tv_usec = 0;

				ret = select(fd + 1, NULL, &w_fds, NULL, &tv);

				if (ret > 0) {
					errnosize = sizeof(connect_errno);

					ret = getsockopt(fd, SOL_SOCKET,
							SO_ERROR, &connect_errno, &errnosize);

					if (ret >= 0 && connect_errno == 0) {
						/* Connect succeed */
						goto out;
					}
				}

				slept = CONNECT_TIMEOUT;
				break;
			case EAGAIN:
				slept = rand() % 3 + 1;
				sleep(slept);
				break;
			default:
				goto error_out;
		}

	}

  out:

	return fd;

  error_out:

	close(fd);
#endif // _XBOX
	return -1;
}