static void ReadConfigFile(void)
{
  FILE *fp;
  char buf[256], buf2[256];
  int line;
  int len;
  int n, i, j;
  struct stat sb;

  if ((fp = fopen(rfbAuthConfigFile, "r")) == NULL)
    return;

  if (fstat(fileno(fp), &sb) == -1)
    FatalError("rfbAuthInit: ERROR: fstat %s: %s", rfbAuthConfigFile,
               strerror(errno));

  if ((sb.st_uid != 0) && (sb.st_uid != getuid()))
    FatalError("ERROR: %s must be owned by you or by root", rfbAuthConfigFile);

  if (sb.st_mode & (S_IWGRP | S_IWOTH))
    FatalError("ERROR: %s cannot have group or global write permissions",
               rfbAuthConfigFile);

  rfbLog("Using security configuration file %s\n", rfbAuthConfigFile);
  for (line = 0; fgets(buf, sizeof(buf), fp) != NULL; line++) {
    len = strlen(buf) - 1;
    if (buf[len] != '\n' && strlen(buf) == 256)
      FatalError("ERROR in %s: line %d is too long!", rfbAuthConfigFile,
                 line + 1);

    buf[len] = '\0';

    for (i = 0, j = 0; i < len; i++) {
      if (buf[i] != ' ' && buf[i] != '\t')
        buf2[j++] = buf[i];
    }
    len = j;
    buf2[len] = '\0';
    if (len < 1) continue;

    if (!strcmp(buf2, "no-remote-resize")) {
      rfbAuthDisableRemoteResize = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-reverse-connections")) {
      rfbAuthDisableRevCon = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-remote-connections")) {
      interface.s_addr = htonl(INADDR_LOOPBACK);
      interface6 = in6addr_loopback;
      continue;
    }

    if (!strcmp(buf2, "no-clipboard-send")) {
      rfbAuthDisableCBSend = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-clipboard-recv")) {
      rfbAuthDisableCBRecv = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-httpd")) {
      rfbAuthDisableHTTP = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-x11-tcp-connections")) {
      rfbAuthDisableX11TCP = TRUE;
      continue;
    }

#ifdef XVNC_AuthPAM
    if (!strcmp(buf2, "no-pam-sessions")) {
      rfbAuthDisablePAMSession = TRUE;
      continue;
    }

    if (!strcmp(buf2, "enable-user-acl")) {
      rfbAuthUserACL = TRUE;
      continue;
    }

    n = 17;
    if (!strncmp(buf2, "pam-service-name=", n)) {
      if (buf2[n] == '\0')
        FatalError("ERROR in %s: pam-service-name is empty!",
                   rfbAuthConfigFile);

      if ((pamServiceName = strdup(&buf2[n])) == NULL)
        FatalError("rfbAuthInit strdup: %s", strerror(errno));

      continue;
    }
#endif

    /* permitted-auth-methods provides backward compatibility with TurboVNC
       2.0.x and earlier.  It can only be used to enable non-VeNCrypt
       security types. */
    n = 23;
    if (!strncmp(buf2, "permitted-auth-methods=", n)) {
      if (buf2[n] == '\0')
        FatalError("ERROR in %s: permitted-auth-methods is empty!",
                   rfbAuthConfigFile);

      setSecTypes(&buf2[n], TRUE);
      continue;
    }

    /* permitted-security-types was introduced in TurboVNC 2.1. */
    n = 25;
    if (!strncmp(buf2, "permitted-security-types=", n)) {
      if (buf2[n] == '\0')
        FatalError("ERROR in %s: permitted-security-types is empty!",
                   rfbAuthConfigFile);

      setSecTypes(&buf2[n], FALSE);
      continue;
    }

#ifdef USETLS
    n = 24;
    if (!strncmp(buf2, "permitted-cipher-suites=", n)) {
      if (buf2[n] == '\0')
        FatalError("ERROR in %s: permitted-cipher-suites is empty!",
                   rfbAuthConfigFile);

      if ((rfbAuthCipherSuites = strdup(&buf2[n])) == NULL)
        FatalError("rfbAuthInit strdup: %s", strerror(errno));

      continue;
    }
#endif

    n = 17;
    if (!strncmp(buf2, "max-idle-timeout=", n)) {
      int t;

      if (buf2[n] == '\0')
        FatalError("ERROR in %s: max-idle-timeout is empty!",
                   rfbAuthConfigFile);

      if (sscanf(&buf2[n], "%d", &t) < 1 || t <= 0)
        FatalError("ERROR in %s: max-idle-timeout value must be > 0!",
                   rfbAuthConfigFile);

      rfbMaxIdleTimeout = (CARD32)t;
      continue;
    }

    n = 17;
    if (!strncmp(buf2, "max-desktop-size=", n)) {
      int w = -1, h = -1;

      if (buf2[n] == '\0')
        FatalError("ERROR in %s: max-desktop-size is empty!",
                   rfbAuthConfigFile);

      if (sscanf(&buf2[n], "%dx%d", &w, &h) < 2 || w <= 0 || h <= 0)
        FatalError("ERROR in %s: max-desktop-size value is incorrect.",
                   rfbAuthConfigFile);

      if (w == 0) w = MAXSHORT;
      if (h == 0) h = MAXSHORT;
      rfbMaxWidth = (CARD32)w;
      rfbMaxHeight = (CARD32)h;
      continue;
    }

    if (buf2[0] != '#')
      rfbLog("WARNING: unrecognized security config line '%s'\n", buf);
  }

  fclose(fp);
}
static void ReadConfigFile(void)
{
  FILE *fp;
  char buf[256], buf2[256];
  int line;
  int len;
  int n, i, j;
  struct stat sb;

  if ((fp = fopen(rfbAuthConfigFile, "r")) == NULL)
    return;

  if (fstat(fileno(fp), &sb) == -1)
    FatalError("rfbAuthInit: ERROR: fstat %s: %s", rfbAuthConfigFile,
               strerror(errno));

  if ((sb.st_uid != 0) && (sb.st_uid != getuid()))
    FatalError("ERROR: %s must be owned by you or by root", rfbAuthConfigFile);

  if (sb.st_mode & (S_IWGRP | S_IWOTH))
    FatalError("ERROR: %s cannot have group or global write permissions",
               rfbAuthConfigFile);

  rfbLog("Using security configuration file %s\n", rfbAuthConfigFile);
  for (line = 0; fgets(buf, sizeof(buf), fp) != NULL; line++) {
    len = strlen(buf) - 1;
    if (buf[len] != '\n' && strlen(buf) == 256)
      FatalError("ERROR in %s: line %d is too long!", rfbAuthConfigFile,
                 line + 1);

    buf[len] = '\0';

    for (i = 0, j = 0; i < len; i++) {
      if (buf[i] != ' ' && buf[i] != '\t')
        buf2[j++] = buf[i];
    }
    len = j;
    buf2[len] = '\0';
    if (len < 1) continue;

    if (!strcmp(buf2, "no-remote-resize")) {
      rfbAuthDisableRemoteResize = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-reverse-connections")) {
      rfbAuthDisableRevCon = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-remote-connections")) {
      interface.s_addr = htonl(INADDR_LOOPBACK);
      interface6 = in6addr_loopback;
      continue;
    }

    if (!strcmp(buf2, "no-clipboard-send")) {
      rfbAuthDisableCBSend = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-clipboard-recv")) {
      rfbAuthDisableCBRecv = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-httpd")) {
      rfbAuthDisableHTTP = TRUE;
      continue;
    }

    if (!strcmp(buf2, "no-x11-tcp-connections")) {
      rfbAuthDisableX11TCP = TRUE;
      continue;
    }

#ifdef XVNC_AuthPAM
    if (!strcmp(buf2, "no-pam-sessions")) {
      rfbAuthDisablePAMSession = TRUE;
      continue;
    }

    if (!strcmp(buf2, "enable-user-acl")) {
      rfbAuthUserACL = TRUE;
      continue;
    }

    n = 17;
    if (!strncmp(buf2, "pam-service-name=", n)) {
      if (buf2[n] == '\0')
        FatalError("ERROR in %s: pam-service-name is empty!",
                   rfbAuthConfigFile);

      if ((pamServiceName = strdup(&buf2[n])) == NULL)
        FatalError("rfbAuthInit strdup: %s", strerror(errno));

      continue;
    }
#endif

     
    n = 23;
    if (!strncmp(buf2, "permitted-auth-methods=", n)) {
      if (buf2[n] == '\0')
        FatalError("ERROR in %s: permitted-auth-methods is empty!",
                   rfbAuthConfigFile);

      setSecTypes(&buf2[n], TRUE);
      continue;
    }

     
    n = 25;
    if (!strncmp(buf2, "permitted-security-types=", n)) {
      if (buf2[n] == '\0')
        FatalError("ERROR in %s: permitted-security-types is empty!",
                   rfbAuthConfigFile);

      setSecTypes(&buf2[n], FALSE);
      continue;
    }

#ifdef USETLS
    n = 24;
    if (!strncmp(buf2, "permitted-cipher-suites=", n)) {
      if (buf2[n] == '\0')
        FatalError("ERROR in %s: permitted-cipher-suites is empty!",
                   rfbAuthConfigFile);

      if ((rfbAuthCipherSuites = strdup(&buf2[n])) == NULL)
        FatalError("rfbAuthInit strdup: %s", strerror(errno));

      continue;
    }
#endif

    n = 17;
    if (!strncmp(buf2, "max-idle-timeout=", n)) {
      int t;

      if (buf2[n] == '\0')
        FatalError("ERROR in %s: max-idle-timeout is empty!",
                   rfbAuthConfigFile);

      if (sscanf(&buf2[n], "%d", &t) < 1 || t <= 0)
        FatalError("ERROR in %s: max-idle-timeout value must be > 0!",
                   rfbAuthConfigFile);

      rfbMaxIdleTimeout = (CARD32)t;
      continue;
    }

    n = 17;
    if (!strncmp(buf2, "max-desktop-size=", n)) {
      int w = -1, h = -1;

      if (buf2[n] == '\0')
        FatalError("ERROR in %s: max-desktop-size is empty!",
                   rfbAuthConfigFile);

      if (sscanf(&buf2[n], "%dx%d", &w, &h) < 2 || w <= 0 || h <= 0)
        FatalError("ERROR in %s: max-desktop-size value is incorrect.",
                   rfbAuthConfigFile);

      if (w == 0) w = MAXSHORT;
      if (h == 0) h = MAXSHORT;
      rfbMaxWidth = (CARD32)w;
      rfbMaxHeight = (CARD32)h;
      continue;
    }

    if (buf2[0] != '#')
      rfbLog("WARNING: unrecognized security config line '%s'\n", buf);
  }

  fclose(fp);
}