int NCONF_load_bio()

in crypto/conf/conf.c [383:579]


int NCONF_load_bio(CONF *conf, BIO *in, long *out_error_line) {
  static const size_t CONFBUFSIZE = 512;
  int bufnum = 0, i, ii;
  BUF_MEM *buff = NULL;
  char *s, *p, *end;
  int again;
  long eline = 0;
  char btmp[DECIMAL_SIZE(eline) + 1];
  CONF_VALUE *v = NULL, *tv;
  CONF_VALUE *sv = NULL;
  char *section = NULL, *buf;
  char *start, *psection, *pname;

  if ((buff = BUF_MEM_new()) == NULL) {
    OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB);
    goto err;
  }

  section = OPENSSL_strdup(kDefaultSectionName);
  if (section == NULL) {
    goto err;
  }

  sv = NCONF_new_section(conf, section);
  if (sv == NULL) {
    OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
    goto err;
  }

  bufnum = 0;
  again = 0;
  for (;;) {
    if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
      OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB);
      goto err;
    }
    p = &(buff->data[bufnum]);
    *p = '\0';
    BIO_gets(in, p, CONFBUFSIZE - 1);
    p[CONFBUFSIZE - 1] = '\0';
    ii = i = strlen(p);
    if (i == 0 && !again) {
      break;
    }
    again = 0;
    while (i > 0) {
      if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) {
        break;
      } else {
        i--;
      }
    }
    // we removed some trailing stuff so there is a new
    // line on the end.
    if (ii && i == ii) {
      again = 1;  // long line
    } else {
      p[i] = '\0';
      eline++;  // another input line
    }

    // we now have a line with trailing \r\n removed

    // i is the number of bytes
    bufnum += i;

    v = NULL;
    // check for line continuation
    if (bufnum >= 1) {
      // If we have bytes and the last char '\\' and
      // second last char is not '\\'
      p = &(buff->data[bufnum - 1]);
      if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
        bufnum--;
        again = 1;
      }
    }
    if (again) {
      continue;
    }
    bufnum = 0;
    buf = buff->data;

    clear_comments(conf, buf);
    s = eat_ws(conf, buf);
    if (IS_EOF(conf, *s)) {
      continue;  // blank line
    }
    if (*s == '[') {
      char *ss;

      s++;
      start = eat_ws(conf, s);
      ss = start;
    again:
      end = eat_alpha_numeric(conf, ss);
      p = eat_ws(conf, end);
      if (*p != ']') {
        if (*p != '\0' && ss != p) {
          ss = p;
          goto again;
        }
        OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
        goto err;
      }
      *end = '\0';
      if (!str_copy(conf, NULL, &section, start)) {
        goto err;
      }
      if ((sv = get_section(conf, section)) == NULL) {
        sv = NCONF_new_section(conf, section);
      }
      if (sv == NULL) {
        OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
        goto err;
      }
      continue;
    } else {
      pname = s;
      psection = NULL;
      end = eat_alpha_numeric(conf, s);
      if ((end[0] == ':') && (end[1] == ':')) {
        *end = '\0';
        end += 2;
        psection = pname;
        pname = end;
        end = eat_alpha_numeric(conf, end);
      }
      p = eat_ws(conf, end);
      if (*p != '=') {
        OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_EQUAL_SIGN);
        goto err;
      }
      *end = '\0';
      p++;
      start = eat_ws(conf, p);
      while (!IS_EOF(conf, *p)) {
        p++;
      }
      p--;
      while ((p != start) && (IS_WS(conf, *p))) {
        p--;
      }
      p++;
      *p = '\0';

      if (!(v = CONF_VALUE_new())) {
        goto err;
      }
      if (psection == NULL) {
        psection = section;
      }
      v->name = OPENSSL_strdup(pname);
      if (v->name == NULL) {
        goto err;
      }
      if (!str_copy(conf, psection, &(v->value), start)) {
        goto err;
      }

      if (strcmp(psection, section) != 0) {
        if ((tv = get_section(conf, psection)) == NULL) {
          tv = NCONF_new_section(conf, psection);
        }
        if (tv == NULL) {
          OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
          goto err;
        }
      } else {
        tv = sv;
      }
      if (add_string(conf, tv, v) == 0) {
        goto err;
      }
      v = NULL;
    }
  }
  BUF_MEM_free(buff);
  OPENSSL_free(section);
  return 1;

err:
  BUF_MEM_free(buff);
  OPENSSL_free(section);
  if (out_error_line != NULL) {
    *out_error_line = eline;
  }
  snprintf(btmp, sizeof btmp, "%ld", eline);
  ERR_add_error_data(2, "line ", btmp);

  if (v != NULL) {
    OPENSSL_free(v->name);
    OPENSSL_free(v->value);
    OPENSSL_free(v);
  }
  return 0;
}