static X509_NAME *do_subject(char *subject)
	{
	size_t buflen = strlen (subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
	char *buf = malloc (buflen);
	size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
	char **ne_types = malloc (max_ne * sizeof (char *));
	char **ne_values = malloc (max_ne * sizeof (char *));

	char *sp = subject, *bp = buf;
	int i, ne_num = 0;

	X509_NAME *n = NULL;
	int nid;

	if (!buf || !ne_types || !ne_values)
	{
		BIO_printf(bio_err, "malloc error\n");
		goto error0;
	}

	if (*subject != '/')
	{
		BIO_printf(bio_err, "Subject does not start with '/'.\n");
		goto error0;
	}
	sp++; /* skip leading / */

	while (*sp)
	{
		/* collect type */
		ne_types[ne_num] = bp;
		while (*sp)
		{
			if (*sp == '\\') /* is there anything to escape in the type...? */
				if (*++sp)
					*bp++ = *sp++;
				else
				{
					BIO_printf(bio_err, "escape character at end of string\n");
					goto error0;
				}
			else if (*sp == '=')
			{
				sp++;
				*bp++ = '\0';
				break;
			}
			else
				*bp++ = *sp++;
		}
		if (!*sp)
		{
			BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
			goto error0;
		}
		ne_values[ne_num] = bp;
		while (*sp)
		{
			if (*sp == '\\')
				if (*++sp)
					*bp++ = *sp++;
				else
				{
					BIO_printf(bio_err, "escape character at end of string\n");
					goto error0;
				}
			else if (*sp == '/')
			{
				sp++;
				*bp++ = '\0';
				break;
			}
			else
				*bp++ = *sp++;
		}
		*bp++ = '\0';
		ne_num++;
	}

	if (!(n = X509_NAME_new()))
		goto error0;

	for (i = 0; i < ne_num; i++)
		{
		if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
			{
			BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
			continue;
			}

		if (!*ne_values[i])
			{
			BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
			continue;
			}

		if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_values[i], -1,-1,0))
			goto error1;
		}

	free (ne_values);
	free (ne_types);
	free (buf);
	return n;

error1:
	X509_NAME_free(n);
error0:
	free (ne_values);
	free (ne_types);
	free (buf);
	return NULL;
}