[PATCH] Add support for MS Catalog files

Jeremy Allison jra at samba.org
Fri Jun 22 18:06:02 UTC 2018


A few more tiny comments inline. Nearly done :-).

On Fri, Jun 22, 2018 at 03:54:49PM +0200, Andreas Schneider wrote:
> +static int mscat_asn1_read_value(TALLOC_CTX *mem_ctx,
> +				 asn1_node root,
> +				 const char *name,
> +				 DATA_BLOB *blob)
> +{
> +	DATA_BLOB tmp;
> +	unsigned int etype = ASN1_ETYPE_INVALID;
> +	int len = 0;
> +	int rc;
> +
> +	rc = asn1_read_value_type(root, name, NULL, &len, &etype);
> +	if (rc != ASN1_SUCCESS && len == 0) {
> +		return rc;
> +	}
> +
> +	if (etype == ASN1_ETYPE_BIT_STRING) {
> +		if (len + 7 < len) {
> +			return -1;
> +		}
> +		len = (len + 7) / 8;
> +	}
> +
> +	if (len == 0) {
> +		*blob = data_blob_null;
> +		return 0;
> +	}
> +
> +	if (len + 1 < len) {
> +		return -1;
> +	}
> +	tmp = data_blob_talloc_zero(mem_ctx, len + 1);
> +	if (tmp.data == NULL) {
> +		return -1;
> +	}
> +
> +	rc = asn1_read_value(root,
> +			     name,
> +			     tmp.data,
> +			     &len);
> +	if (rc != ASN1_SUCCESS) {
> +		data_blob_free(&tmp);
> +		return rc;
> +	}
> +
> +	if (etype == ASN1_ETYPE_BIT_STRING) {
> +		len = (len + 7) / 8;
> +		if (len + 7 < len) {
> +			return -1;

The check needs to be before the use (as you've
done in the previous case above).

> +
> +static int mscat_ctl_cleanup(struct mscat_ctl *ctl)
> +{
> +	if (ctl->asn1_desc != ASN1_TYPE_EMPTY) {
> +		asn1_delete_structure(&ctl->asn1_desc);
> +	}
> +
> +	return 0;
> +}
> +
> +struct mscat_ctl *mscat_ctl_init(TALLOC_CTX *mem_ctx)
> +{
> +	char error_string[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = {0};
> +	struct mscat_ctl *cat_ctl;
> +	int rc;
> +
> +	cat_ctl = talloc_zero(mem_ctx, struct mscat_ctl);
> +	if (cat_ctl == NULL) {
> +		return NULL;
> +	}
> +	talloc_set_destructor(cat_ctl, mscat_ctl_cleanup);
> +
> +	cat_ctl->asn1_desc = ASN1_TYPE_EMPTY;
> +	cat_ctl->tree_ctl = ASN1_TYPE_EMPTY;
> +
> +	rc = asn1_array2tree(mscat_asn1_tab,
> +			     &cat_ctl->asn1_desc,
> +			     error_string);
> +	if (rc != ASN1_SUCCESS) {
> +		talloc_free(cat_ctl);
> +		asn1_perror(rc);
> +		DBG_ERR("Failed to create parser tree: %s",
> +			error_string);
> +		return NULL;
> +	}
> +
> +	return cat_ctl;
> +}
> +
> +int mscat_ctl_import(struct mscat_ctl *ctl,
> +		     struct mscat_pkcs7 *pkcs7)
> +{
> +	char error_string[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = {0};
> +	TALLOC_CTX *tmp_ctx = NULL;
> +	char *oid;
> +	bool ok;
> +	int rc;
> +
> +	rc = gnutls_pkcs7_get_embedded_data(pkcs7->c,
> +					    GNUTLS_PKCS7_EDATA_GET_RAW,
> +					    &ctl->raw_ctl);
> +	if (rc != GNUTLS_E_SUCCESS) {
> +		DBG_ERR("Failed to get embedded data from pkcs7: %s",
> +			gnutls_strerror(rc));
> +		return -1;
> +	}
> +
> +	rc = asn1_create_element(ctl->asn1_desc,
> +				 "CATALOG.CertTrustList",
> +				 &ctl->tree_ctl);
> +	if (rc != ASN1_SUCCESS) {
> +		asn1_perror(rc);
> +		DBG_ERR("Failed to create CertTrustList ASN.1 element");
> +		return -1;
> +	}
> +
> +	rc = asn1_der_decoding(&ctl->tree_ctl,
> +			       ctl->raw_ctl.data,
> +			       ctl->raw_ctl.size,
> +			       error_string);
> +	if (rc != ASN1_SUCCESS) {
> +		asn1_perror(rc);
> +		DBG_ERR("Failed to parse ASN.1 CertTrustList: %s",
> +			error_string);
> +		return -1;
> +	}
> +
> +	tmp_ctx = talloc_new(ctl);
> +	if (tmp_ctx == NULL) {
> +		return -1;
> +	}
> +
> +	oid = mscat_asn1_get_oid(tmp_ctx,
> +				 ctl->tree_ctl,
> +				 "catalogListId.oid");
> +	if (oid == NULL) {
> +		rc = -1;
> +		goto done;
> +	}
> +
> +	ok = mscat_asn1_oid_equal(oid, CATALOG_LIST_OBJOID);
> +	if (!ok) {
> +		DBG_ERR("Invalid oid (%s), expected CATALOG_LIST_OBJOID",
> +			oid);
> +		rc = -1;
> +		goto done;
> +	}
> +	talloc_free(oid);
> +
> +	oid = mscat_asn1_get_oid(tmp_ctx,
> +				 ctl->tree_ctl,
> +				 "catalogListMemberId.oid");
> +	if (oid == NULL) {
> +		rc = -1;
> +		goto done;
> +	}
> +
> +	ok = mscat_asn1_oid_equal(oid, CATALOG_LIST_MEMBER_V2_OBJOID);
> +	if (ok) {
> +		ctl->version = 2;
> +	} else {
> +		ok = mscat_asn1_oid_equal(oid, CATALOG_LIST_MEMBER_OBJOID);
> +		if (ok) {
> +			ctl->version = 1;
> +		} else {
> +			DBG_ERR("Invalid oid (%s), expected "
> +				"CATALOG_LIST_MEMBER_OBJOID",
> +				oid);
> +			rc = -1;
> +			goto done;
> +		}
> +	}
> +
> +	rc = 0;
> +done:
> +	talloc_free(tmp_ctx);
> +	return rc;
> +}
> +
> +static int ctl_get_member_checksum_string(struct mscat_ctl *ctl,
> +					  TALLOC_CTX *mem_ctx,
> +					  unsigned int idx,
> +					  const char **pchecksum,
> +					  size_t *pchecksum_size)
> +{
> +	TALLOC_CTX *tmp_ctx;
> +	DATA_BLOB chksum_ucs2;
> +	size_t converted_size = 0;
> +	char *checksum;
> +	char *element;
> +	int rc = -1;
> +	bool ok;
> +
> +	tmp_ctx = talloc_new(mem_ctx);
> +	if (tmp_ctx == NULL) {
> +		return -1;
> +	}
> +
> +	element = talloc_asprintf(tmp_ctx,
> +				  "members.?%u.checksum",
> +				  idx);
> +	if (element == NULL) {
> +		goto done;
> +	}
> +
> +	rc = mscat_asn1_read_value(tmp_ctx,
> +				   ctl->tree_ctl,
> +				   element,
> +				   &chksum_ucs2);
> +	talloc_free(element);
> +	if (rc != 0) {
> +		goto done;
> +	}
> +
> +	ok = convert_string_talloc(mem_ctx,
> +				   CH_UTF16LE,
> +				   CH_UNIX,
> +				   chksum_ucs2.data,
> +				   chksum_ucs2.length,
> +				   (void **)&checksum,
> +				   &converted_size);
> +	if (!ok) {
> +		rc = -1;
> +		goto done;
> +	}
> +
> +	*pchecksum = talloc_steal(mem_ctx, checksum);
> +	*pchecksum_size = strlen(checksum + 1);

Shouldn't the above be:

	*pchecksum_size = strlen(checksum) + 1;

> +				goto done;
> +			}
> +
> +			DBG_DEBUG("Parsed NameValue: name=%s, flags=%u, value=%s",
> +				  name,
> +				  flags,
> +				  value);
> +
> +			cmp = strcmp(name, "File");
> +			if (cmp == 0) {
> +				m->file.name = talloc_steal(m, value);
> +				m->file.flags = flags;
> +
> +				continue;
> +			}
> +
> +			cmp = strcmp(name, "OSAttr");
> +			if (cmp == 0) {
> +				m->osattr.value = talloc_steal(m, value);
> +				m->osattr.flags = flags;
> +
> +				continue;
> +			}
> +		}
> +
> +		ok = mscat_asn1_oid_equal(oid, CAT_MEMBERINFO_OBJID);
> +		if (ok) {
> +			char *name;

Initialize name to NULL please.

Really nice work Andreas, thanks.

Just one sylistic comment. Instead of using
talloc_steal(), can you use talloc_move()
instead ?

talloc_move() nulls out the moved pointer,
making it more likely to crash on erroneous
reuse rather than corrupt stuff (which is
preferable IMHO).

I can't see a place where it matters in this
code, so feel free to ignore my advice here
(I won't block the patch if you don't do this :-).

Cheers,

	Jeremy.



More information about the samba-technical mailing list