static void AuthPAMUserPwdRspFunc(rfbClientPtr cl)
{
  CARD32 userLen;
  CARD32 pwdLen;
  char userBuf[MAX_USER_LEN + 1];
  char pwdBuf[MAX_PWD_LEN + 1];
  int n;
  const char *emsg;

  n = ReadExact(cl, (char *)&userLen, sizeof(userLen));
  if (n <= 0) {
    if (n != 0)
      rfbLogPerror("AuthPAMUserPwdRspFunc: read error");
    rfbCloseClient(cl);
    return;
  }

  userLen = Swap32IfLE(userLen);
  n = ReadExact(cl, (char *)&pwdLen, sizeof(pwdLen));
  if (n <= 0) {
    if (n != 0)
      rfbLogPerror("AuthPAMUserPwdRspFunc: read error");
    rfbCloseClient(cl);
    return;
  }

  pwdLen = Swap32IfLE(pwdLen);
  if ((userLen > MAX_USER_LEN) || (pwdLen > MAX_PWD_LEN)) {
    rfbLogPerror("AuthPAMUserPwdRspFunc: excessively large user name or password in response");
    rfbCloseClient(cl);
    return;
  }

  n = ReadExact(cl, userBuf, userLen);
  if (n <= 0) {
    if (n != 0)
      rfbLogPerror("AuthPAMUserPwdRspFunc: error reading user name");
    rfbCloseClient(cl);
    return;
  }

  userBuf[userLen] = '\0';
  n = ReadExact(cl, pwdBuf, pwdLen);
  if (n <= 0) {
    if (n != 0)
      rfbLogPerror("AuthPAMUserPwdRspFunc: error reading password");
    rfbCloseClient(cl);
    return;
  }

  pwdBuf[pwdLen] = '\0';
  if (rfbAuthUserACL) {
    UserList *p = userACL;

    if (p == NULL)
      rfbLog("WARNING: User ACL is empty.  No users will be allowed to log in with Unix Login authentication.\n");

    while (p != NULL) {
      if (!strcmp(p->name, userBuf))
        break;
      p = p->next;
    }

    if (p == NULL) {
      rfbLog("User '%s' is not in the ACL and has been denied access\n",
             userBuf);
      rfbClientAuthFailed(cl, "User denied access");
      return;
    }

    cl->viewOnly = p->viewOnly;
  } else {
    struct passwd pbuf;
    struct passwd *pw;
    char buf[256];

    if (getpwuid_r(getuid(), &pbuf, buf, sizeof(buf), &pw) != 0)
      FatalError("AuthPAMUserPwdRspFunc: getpwuid_r failed: %s",
                 strerror(errno));

    if (strcmp(pbuf.pw_name, userBuf)) {
      rfbLog("User '%s' denied access (not the session owner)\n", userBuf);
      rfbLog("  Enable user ACL to grant access to other users.\n");
      rfbClientAuthFailed(cl, "User denied access");
      return;
    }
  }

  if (rfbPAMAuthenticate(cl, pamServiceName, userBuf, pwdBuf, &emsg))
    rfbClientAuthSucceeded(cl, rfbAuthUnixLogin);
  else
    rfbClientAuthFailed(cl, (char *)emsg);
}
static void AuthPAMUserPwdRspFunc(rfbClientPtr cl)
{
  CARD32 userLen;
  CARD32 pwdLen;
  char userBuf[MAX_USER_LEN + 1];
  char pwdBuf[MAX_PWD_LEN + 1];
  int n;
  const char *emsg;

  n = ReadExact(cl, (char *)&userLen, sizeof(userLen));
  if (n <= 0) {
    if (n != 0)
      rfbLogPerror("AuthPAMUserPwdRspFunc: read error");
    rfbCloseClient(cl);
    return;
  }

  userLen = Swap32IfLE(userLen);
  n = ReadExact(cl, (char *)&pwdLen, sizeof(pwdLen));
  if (n <= 0) {
    if (n != 0)
      rfbLogPerror("AuthPAMUserPwdRspFunc: read error");
    rfbCloseClient(cl);
    return;
  }

  pwdLen = Swap32IfLE(pwdLen);
  if ((userLen > MAX_USER_LEN) || (pwdLen > MAX_PWD_LEN)) {
    rfbLogPerror("AuthPAMUserPwdRspFunc: excessively large user name or password in response");
    rfbCloseClient(cl);
    return;
  }

  n = ReadExact(cl, userBuf, userLen);
  if (n <= 0) {
    if (n != 0)
      rfbLogPerror("AuthPAMUserPwdRspFunc: error reading user name");
    rfbCloseClient(cl);
    return;
  }

  userBuf[userLen] = '\0';
  n = ReadExact(cl, pwdBuf, pwdLen);
  if (n <= 0) {
    if (n != 0)
      rfbLogPerror("AuthPAMUserPwdRspFunc: error reading password");
    rfbCloseClient(cl);
    return;
  }

  pwdBuf[pwdLen] = '\0';
  if (rfbAuthUserACL) {
    UserList *p = userACL;

    if (p == NULL)
      rfbLog("WARNING: User ACL is empty.  No users will be allowed to log in with Unix Login authentication.\n");

    while (p != NULL) {
      if (!strcmp(p->name, userBuf))
        break;
      p = p->next;
    }

    if (p == NULL) {
      rfbLog("User '%s' is not in the ACL and has been denied access\n",
             userBuf);
      rfbClientAuthFailed(cl, "User denied access");
      return;
    }

    cl->viewOnly = p->viewOnly;
  } else {
    struct passwd pbuf;
    struct passwd *pw;
    char buf[256];

    if (getpwuid_r(getuid(), &pbuf, buf, sizeof(buf), &pw) != 0)
      FatalError("AuthPAMUserPwdRspFunc: getpwuid_r failed: %s",
                 strerror(errno));

    if (strcmp(pbuf.pw_name, userBuf)) {
      rfbLog("User '%s' denied access (not the session owner)\n", userBuf);
      rfbLog("  Enable user ACL to grant access to other users.\n");
      rfbClientAuthFailed(cl, "User denied access");
      return;
    }
  }

  if (rfbPAMAuthenticate(cl, pamServiceName, userBuf, pwdBuf, &emsg))
    rfbClientAuthSucceeded(cl, rfbAuthUnixLogin);
  else
    rfbClientAuthFailed(cl, (char *)emsg);
}