// Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <openssl/x509.h>

#include <assert.h>
#include <inttypes.h>
#include <string.h>

#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/obj.h>


static int maybe_write(BIO *out, const void *buf, int len) {
  // If |out| is NULL, ignore the output but report the length.
  return out == NULL || BIO_write(out, buf, len) == len;
}

// do_indent prints |indent| spaces to |out|.
static int do_indent(BIO *out, int indent) {
  for (int i = 0; i < indent; i++) {
    if (!maybe_write(out, " ", 1)) {
      return 0;
    }
  }
  return 1;
}

#define FN_WIDTH_LN 25
#define FN_WIDTH_SN 10

static int do_name_ex(BIO *out, const X509_NAME *n, int indent,
                      unsigned long flags) {
  int prev = -1, orflags;
  char objtmp[80];
  const char *objbuf;
  int outlen, len;
  const char *sep_dn, *sep_mv, *sep_eq;
  int sep_dn_len, sep_mv_len, sep_eq_len;
  if (indent < 0) {
    indent = 0;
  }
  outlen = indent;
  if (!do_indent(out, indent)) {
    return -1;
  }
  switch (flags & XN_FLAG_SEP_MASK) {
    case XN_FLAG_SEP_MULTILINE:
      sep_dn = "\n";
      sep_dn_len = 1;
      sep_mv = " + ";
      sep_mv_len = 3;
      break;

    case XN_FLAG_SEP_COMMA_PLUS:
      sep_dn = ",";
      sep_dn_len = 1;
      sep_mv = "+";
      sep_mv_len = 1;
      indent = 0;
      break;

    case XN_FLAG_SEP_CPLUS_SPC:
      sep_dn = ", ";
      sep_dn_len = 2;
      sep_mv = " + ";
      sep_mv_len = 3;
      indent = 0;
      break;

    case XN_FLAG_SEP_SPLUS_SPC:
      sep_dn = "; ";
      sep_dn_len = 2;
      sep_mv = " + ";
      sep_mv_len = 3;
      indent = 0;
      break;

    default:
      return -1;
  }

  if (flags & XN_FLAG_SPC_EQ) {
    sep_eq = " = ";
    sep_eq_len = 3;
  } else {
    sep_eq = "=";
    sep_eq_len = 1;
  }

  int cnt = X509_NAME_entry_count(n);
  for (int i = 0; i < cnt; i++) {
    const X509_NAME_ENTRY *ent;
    if (flags & XN_FLAG_DN_REV) {
      ent = X509_NAME_get_entry(n, cnt - i - 1);
    } else {
      ent = X509_NAME_get_entry(n, i);
    }
    if (prev != -1) {
      if (prev == X509_NAME_ENTRY_set(ent)) {
        if (!maybe_write(out, sep_mv, sep_mv_len)) {
          return -1;
        }
        outlen += sep_mv_len;
      } else {
        if (!maybe_write(out, sep_dn, sep_dn_len)) {
          return -1;
        }
        outlen += sep_dn_len;
        if (!do_indent(out, indent)) {
          return -1;
        }
        outlen += indent;
      }
    }
    prev = X509_NAME_ENTRY_set(ent);
    const ASN1_OBJECT *fn = X509_NAME_ENTRY_get_object(ent);
    const ASN1_STRING *val = X509_NAME_ENTRY_get_data(ent);
    assert((flags & XN_FLAG_FN_MASK) == XN_FLAG_FN_SN);
    int fn_nid = OBJ_obj2nid(fn);
    if (fn_nid == NID_undef) {
      OBJ_obj2txt(objtmp, sizeof(objtmp), fn, 1);
      objbuf = objtmp;
    } else {
      objbuf = OBJ_nid2sn(fn_nid);
    }
    int objlen = strlen(objbuf);
    if (!maybe_write(out, objbuf, objlen) ||
        !maybe_write(out, sep_eq, sep_eq_len)) {
      return -1;
    }
    outlen += objlen + sep_eq_len;
    // If the field name is unknown then fix up the DER dump flag. We
    // might want to limit this further so it will DER dump on anything
    // other than a few 'standard' fields.
    if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) {
      orflags = ASN1_STRFLGS_DUMP_ALL;
    } else {
      orflags = 0;
    }

    len = ASN1_STRING_print_ex(out, val, flags | orflags);
    if (len < 0) {
      return -1;
    }
    outlen += len;
  }
  return outlen;
}

int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
                       unsigned long flags) {
  if (flags == XN_FLAG_COMPAT) {
    return X509_NAME_print(out, nm, indent);
  }
  return do_name_ex(out, nm, indent, flags);
}

int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
                          unsigned long flags) {
  BIO *bio = NULL;
  if (fp != NULL) {
    // If |fp| is NULL, this function returns the number of bytes without
    // writing.
    bio = BIO_new_fp(fp, BIO_NOCLOSE);
    if (bio == NULL) {
      return -1;
    }
  }
  int ret = X509_NAME_print_ex(bio, nm, indent, flags);
  BIO_free(bio);
  return ret;
}
