Ejemplo n.º 1
0
int
_assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
{
#ifdef HAVE_W32_SYSTEM
  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
    {
      struct sockaddr_in myaddr;
      struct sockaddr_un *unaddr;
      unsigned short port;
      char nonce[16];
      int ret;
      
      unaddr = (struct sockaddr_un *)addr;
      if (read_port_and_nonce (unaddr->sun_path, &port, nonce))
        return -1;
      
      myaddr.sin_family = AF_INET;
      myaddr.sin_port = htons (port); 
      myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
  
      /* Set return values.  */
      unaddr->sun_family = myaddr.sin_family;
      unaddr->sun_port = myaddr.sin_port;
      unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
  
      ret = connect (HANDLE2SOCKET(sockfd), 
                     (struct sockaddr *)&myaddr, sizeof myaddr);
      if (!ret)
        {
          /* Send the nonce. */
          ret = _assuan_io_write (sockfd, nonce, 16);
          if (ret >= 0 && ret != 16)
            {
              errno = EIO;
              ret = -1;
            }
        }
      return ret;
    }
  else
    {
      int res;
      res = connect (HANDLE2SOCKET (sockfd), addr, addrlen);
      if (res < 0)
	errno = _assuan_sock_wsa2errno (WSAGetLastError ());
      return res;
    }      
#else
  return connect (sockfd, addr, addrlen);
#endif
}
Ejemplo n.º 2
0
/* Write to the domain server.  */
static ssize_t
uds_writer (assuan_context_t ctx, const void *buf, size_t buflen)
{
#ifndef HAVE_W32_SYSTEM
  struct msghdr msg;
  struct iovec iovec;
  ssize_t len;

  memset (&msg, 0, sizeof (msg));

  msg.msg_name = NULL;
  msg.msg_namelen = 0;
  msg.msg_iovlen = 1;
  msg.msg_iov = &iovec;
  iovec.iov_base = (void*)buf;
  iovec.iov_len = buflen;

  len = _assuan_sendmsg (ctx, ctx->outbound.fd, &msg, 0);

  return len;
#else /*HAVE_W32_SYSTEM*/
  int res = sendto (HANDLE2SOCKET(ctx->outbound.fd), buf, buflen, 0,
		    (struct sockaddr *)&ctx->serveraddr,
		    sizeof (struct sockaddr_in));
  if (res < 0)
    gpg_err_set_errno ( _assuan_sock_wsa2errno (WSAGetLastError ()));
  return res;
#endif /*HAVE_W32_SYSTEM*/
}
Ejemplo n.º 3
0
/* Close the given file descriptor, created with _assuan_pipe or one
   of the socket functions.  Default implementation.  */
int
__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
{
    int rc = closesocket (HANDLE2SOCKET(fd));
    if (rc)
        gpg_err_set_errno ( _assuan_sock_wsa2errno (WSAGetLastError ()) );
    if (rc && WSAGetLastError () == WSAENOTSOCK)
    {
        rc = CloseHandle (fd);
        if (rc)
            /* FIXME. */
            gpg_err_set_errno (EIO);
    }
    return rc;
}
Ejemplo n.º 4
0
int
_assuan_close (assuan_fd_t fd)
{
#ifdef HAVE_W32_SYSTEM
  int rc = closesocket (HANDLE2SOCKET(fd));
  if (rc)
    errno = _assuan_sock_wsa2errno (WSAGetLastError ());
  if (rc && WSAGetLastError () == WSAENOTSOCK)
    {
      rc = CloseHandle (fd);
      if (rc)
	/* FIXME. */
	errno = EIO;
    }
  return rc;
#else
  return close (fd);
#endif
}
Ejemplo n.º 5
0
/* Close the given file descriptor, created with _assuan_pipe or one
   of the socket functions.  Default implementation.  */
int
__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
{
  int rc = closesocket (HANDLE2SOCKET(fd));
  int err = WSAGetLastError ();

  /* Note that gpg_err_set_errno on Windows CE overwrites
     WSAGetLastError() (via SetLastError()).  */
  if (rc)
    gpg_err_set_errno (_assuan_sock_wsa2errno (err));
  if (rc && err == WSAENOTSOCK)
    {
      rc = CloseHandle (fd);
      if (rc)
        /* FIXME. */
        gpg_err_set_errno (EIO);
    }
  return rc;
}
Ejemplo n.º 6
0
static int
accept_connection (assuan_context_t ctx)
{
  assuan_fd_t fd;
  struct sockaddr_un clnt_addr;
  socklen_t len = sizeof clnt_addr;

  fd = SOCKET2HANDLE(accept (HANDLE2SOCKET(ctx->listen_fd), 
                             (struct sockaddr*)&clnt_addr, &len ));
  if (fd == ASSUAN_INVALID_FD)
    {
      ctx->os_errno = errno;
      return _assuan_error (ASSUAN_Accept_Failed);
    }
  if (_assuan_sock_check_nonce (fd, &ctx->listen_nonce))
    {
      _assuan_close (fd);
      ctx->os_errno = EACCES;
      return _assuan_error (ASSUAN_Accept_Failed);
    }

  ctx->connected_fd = fd;
  return accept_connection_bottom (ctx);
}
Ejemplo n.º 7
0
int
_assuan_sock_bind (assuan_context_t ctx, assuan_fd_t sockfd,
		   struct sockaddr *addr, int addrlen)
{
#ifdef HAVE_W32_SYSTEM
  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
    {
      struct sockaddr_in myaddr;
      struct sockaddr_un *unaddr;
      HANDLE filehd;
      int len = sizeof myaddr;
      int rc;
      char nonce[16];
      char tmpbuf[33+16];
      DWORD nwritten;

      if (get_nonce (nonce, 16))
        return -1;

      unaddr = (struct sockaddr_un *)addr;

      myaddr.sin_port = 0;
      myaddr.sin_family = AF_INET;
      myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

      filehd = MyCreateFile (unaddr->sun_path, 
                             GENERIC_WRITE,
                             FILE_SHARE_READ,
                             NULL,
                             CREATE_NEW,
                             FILE_ATTRIBUTE_NORMAL,
                             NULL);
      if (filehd == INVALID_HANDLE_VALUE)
        {
          if (GetLastError () == ERROR_FILE_EXISTS)
            gpg_err_set_errno (WSAEADDRINUSE);
          return -1;
        }

      rc = bind (HANDLE2SOCKET (sockfd), (struct sockaddr *)&myaddr, len);
      if (!rc)
        rc = getsockname (HANDLE2SOCKET (sockfd), 
                          (struct sockaddr *)&myaddr, &len);
      if (rc)
        {
          int save_e = errno;
          CloseHandle (filehd);
          MyDeleteFile (unaddr->sun_path);
          gpg_err_set_errno (save_e);
          return rc;
        }
      snprintf (tmpbuf, sizeof tmpbuf, "%d\n", ntohs (myaddr.sin_port));
      len = strlen (tmpbuf);
      memcpy (tmpbuf+len, nonce,16);
      len += 16;
      
      if (!WriteFile (filehd, tmpbuf, len, &nwritten, NULL))
        {
          CloseHandle (filehd);
          MyDeleteFile (unaddr->sun_path);
          gpg_err_set_errno (EIO);
          return -1;
        }
      CloseHandle (filehd);
      return 0;
    }
  else
    {
      int res = bind (HANDLE2SOCKET(sockfd), addr, addrlen);
      if (res < 0)
	gpg_err_set_errno ( _assuan_sock_wsa2errno (WSAGetLastError ()));
      return res;
    }
#else
  return bind (sockfd, addr, addrlen);
#endif
}
Ejemplo n.º 8
0
ssize_t
__assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
                size_t size)
{
    int res;
    int ec = 0;

    if (is_socket (fd))
    {
        int tries = 3;

again:
        ec = 0;
        res = send (HANDLE2SOCKET (fd), buffer, size, 0);
        if (res == -1)
            ec = WSAGetLastError ();
        if (ec == WSAEWOULDBLOCK && tries--)
        {
            /* EAGAIN: Use select to wait for resources and try again.
               We do this 3 times and then give up.  The higher level
               layer then needs to take care of EAGAIN.  No need to
               specify a timeout - the socket is not expected to be in
               blocking mode.  */
            fd_set fds;

            FD_ZERO (&fds);
            FD_SET (HANDLE2SOCKET (fd), &fds);
            select (0, NULL, &fds, NULL, NULL);
            goto again;
        }
    }
    else
    {
        DWORD nwrite;

        if (!WriteFile (fd, buffer, size, &nwrite, NULL))
        {
            res = -1;
            ec = GetLastError ();
        }
        else
            res = (int)nwrite;
    }
    if (res == -1)
    {
        switch (ec)
        {
        case WSAENOTSOCK:
            gpg_err_set_errno (EBADF);
            break;

        case WSAEWOULDBLOCK:
            gpg_err_set_errno (EAGAIN);
            break;

        case ERROR_BROKEN_PIPE:
        case ERROR_NO_DATA:
            gpg_err_set_errno (EPIPE);
            break;

        default:
            gpg_err_set_errno (EIO);
            break;
        }

    }
    return res;
}
Ejemplo n.º 9
0
int
_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
{
#ifdef HAVE_W32_SYSTEM
  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
    {
      struct sockaddr_in myaddr;
      struct sockaddr_un *unaddr;
      int filefd;
      FILE *fp;
      int len = sizeof myaddr;
      int rc;
      char nonce[16];

      if (get_nonce (nonce, 16))
        return -1;

      unaddr = (struct sockaddr_un *)addr;

      myaddr.sin_port = 0;
      myaddr.sin_family = AF_INET;
      myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

      filefd = open (unaddr->sun_path, 
                     (O_WRONLY|O_CREAT|O_EXCL|O_BINARY), 
                     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
      if (filefd == -1)
        {
          if (errno == EEXIST)
            errno = WSAEADDRINUSE;
          return -1;
        }
      fp = fdopen (filefd, "wb");
      if (!fp)
        { 
          int save_e = errno;
          close (filefd);
          errno = save_e;
          return -1;
        }

      rc = bind (HANDLE2SOCKET (sockfd), (struct sockaddr *)&myaddr, len);
      if (!rc)
        rc = getsockname (HANDLE2SOCKET (sockfd), 
                          (struct sockaddr *)&myaddr, &len);
      if (rc)
        {
          int save_e = errno;
          fclose (fp);
          remove (unaddr->sun_path);
          errno = save_e;
          return rc;
        }
      fprintf (fp, "%d\n", ntohs (myaddr.sin_port));
      fwrite (nonce, 16, 1, fp);
      fclose (fp);

      return 0;
    }
  else
    {
      int res = bind (HANDLE2SOCKET(sockfd), addr, addrlen);
      if (res < 0)
	errno = _assuan_sock_wsa2errno (WSAGetLastError ());
      return res;
    }
#else
  return bind (sockfd, addr, addrlen);
#endif
}
Ejemplo n.º 10
0
static ssize_t
__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
{
  /* Due to the peculiarities of the W32 API we can't use read for a
     network socket and thus we try to use recv first and fallback to
     read if recv detects that it is not a network socket.  */
  int res;

  TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "__assuan_read", ctx,
	      "fd=0x%x, buffer=%p, size=%i", fd, buffer, size);

#ifdef HAVE_W32CE_SYSTEM
  /* This is a bit of a hack to support stdin over ssh.  Note that
     fread buffers fully while getchar is line buffered.  Weird, but
     that's the way it is.  ASSUAN_STDIN and ASSUAN_STDOUT are
     special handle values that shouldn't occur in the wild.  */
  if (fd == ASSUAN_STDIN)
    {
      int i = 0;
      int chr;
      while (i < size)
	{
	  chr = getchar();
	  if (chr == EOF)
	    break;
	  ((char*)buffer)[i++] = (char) chr;
	  if (chr == '\n')
	    break;
	}
      return TRACE_SYSRES (i);
    }
#endif

  res = recv (HANDLE2SOCKET (fd), buffer, size, 0);
  if (res == -1)
    {
      TRACE_LOG1 ("recv failed: rc=%d", (int)WSAGetLastError ());
      switch (WSAGetLastError ())
        {
        case WSAENOTSOCK:
          {
            DWORD nread = 0;
            
            res = ReadFile (fd, buffer, size, &nread, NULL);
            if (! res)
              {
                TRACE_LOG1 ("ReadFile failed: rc=%d", (int)GetLastError ());
                switch (GetLastError ())
                  {
                  case ERROR_BROKEN_PIPE:
		    gpg_err_set_errno (EPIPE);
		    break;

                  case ERROR_PIPE_NOT_CONNECTED:
                  case ERROR_BUSY:
		    gpg_err_set_errno (EAGAIN);
		    break;

                  default:
		    gpg_err_set_errno (EIO); 
                  }
                res = -1;
              }
            else
              res = (int) nread;
          }
          break;
          
        case WSAEWOULDBLOCK:
	  gpg_err_set_errno (EAGAIN);
	  break;

        case ERROR_BROKEN_PIPE:
	  gpg_err_set_errno (EPIPE);
	  break;

        default:
	  gpg_err_set_errno (EIO);
	  break;
        }
    }
  return TRACE_SYSRES (res);
}
Ejemplo n.º 11
0
/* Read from a unix domain socket using sendmsg.  */
static ssize_t
uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
{
#ifndef HAVE_W32_SYSTEM
  int len = 0;
  /* This loop should be OK.  As FDs are followed by data, the
     readable status of the socket does not change and no new
     select/event-loop round is necessary.  */
  while (!len)  /* No data is buffered.  */
    {
      struct msghdr msg;
      struct iovec iovec;
#ifdef USE_DESCRIPTOR_PASSING
      union {
        struct cmsghdr cm;
        char control[CMSG_SPACE(sizeof (int))];
      } control_u;
      struct cmsghdr *cmptr;
#endif /*USE_DESCRIPTOR_PASSING*/

      memset (&msg, 0, sizeof (msg));

      msg.msg_name = NULL;
      msg.msg_namelen = 0;
      msg.msg_iov = &iovec;
      msg.msg_iovlen = 1;
      iovec.iov_base = buf;
      iovec.iov_len = buflen;
#ifdef USE_DESCRIPTOR_PASSING
      msg.msg_control = control_u.control;
      msg.msg_controllen = sizeof (control_u.control);
#endif

      len = _assuan_recvmsg (ctx, ctx->inbound.fd, &msg, 0);
      if (len < 0)
        return -1;
      if (len == 0)
	return 0;

#ifdef USE_DESCRIPTOR_PASSING
      cmptr = CMSG_FIRSTHDR (&msg);
      if (cmptr && cmptr->cmsg_len == CMSG_LEN (sizeof(int)))
        {
          if (cmptr->cmsg_level != SOL_SOCKET
              || cmptr->cmsg_type != SCM_RIGHTS)
            TRACE0 (ctx, ASSUAN_LOG_SYSIO, "uds_reader", ctx,
		    "unexpected ancillary data received");
          else
            {
              int fd;

	      memcpy (&fd, CMSG_DATA (cmptr), sizeof (fd));

              if (ctx->uds.pendingfdscount >= DIM (ctx->uds.pendingfds))
                {
		  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "uds_reader", ctx,
			  "too many descriptors pending - "
			  "closing received descriptor %d", fd);
                  _assuan_close (ctx, fd);
                }
              else
                ctx->uds.pendingfds[ctx->uds.pendingfdscount++] = fd;
            }
	}
#endif /*USE_DESCRIPTOR_PASSING*/
    }

  return len;
#else /*HAVE_W32_SYSTEM*/
  int res = recvfrom (HANDLE2SOCKET(ctx->inbound.fd), buf, buflen, 0, NULL, NULL);
  if (res < 0)
    gpg_err_set_errno (_assuan_sock_wsa2errno (WSAGetLastError ()));
  return res;
#endif /*HAVE_W32_SYSTEM*/
}