t_x509.c revision 109998
155714Skris/* crypto/asn1/t_x509.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include "cryptlib.h"
6155714Skris#include <openssl/buffer.h>
6255714Skris#include <openssl/bn.h>
63109998Smarkm#ifndef OPENSSL_NO_RSA
6455714Skris#include <openssl/rsa.h>
6555714Skris#endif
66109998Smarkm#ifndef OPENSSL_NO_DSA
6755714Skris#include <openssl/dsa.h>
6855714Skris#endif
6955714Skris#include <openssl/objects.h>
7055714Skris#include <openssl/x509.h>
7155714Skris#include <openssl/x509v3.h>
7255714Skris
73109998Smarkm#ifndef OPENSSL_NO_FP_API
7455714Skrisint X509_print_fp(FILE *fp, X509 *x)
75109998Smarkm	{
76109998Smarkm	return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
77109998Smarkm	}
78109998Smarkm
79109998Smarkmint X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, unsigned long cflag)
8055714Skris        {
8155714Skris        BIO *b;
8255714Skris        int ret;
8355714Skris
8455714Skris        if ((b=BIO_new(BIO_s_file())) == NULL)
8555714Skris		{
8655714Skris		X509err(X509_F_X509_PRINT_FP,ERR_R_BUF_LIB);
8755714Skris                return(0);
8855714Skris		}
8955714Skris        BIO_set_fp(b,fp,BIO_NOCLOSE);
90109998Smarkm        ret=X509_print_ex(b, x, nmflag, cflag);
9155714Skris        BIO_free(b);
9255714Skris        return(ret);
9355714Skris        }
9455714Skris#endif
9555714Skris
9655714Skrisint X509_print(BIO *bp, X509 *x)
97109998Smarkm{
98109998Smarkm	return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
99109998Smarkm}
100109998Smarkm
101109998Smarkmint X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
10255714Skris	{
10355714Skris	long l;
104109998Smarkm	int ret=0,i;
105109998Smarkm	char *m=NULL,mlch = ' ';
106109998Smarkm	int nmindent = 0;
10755714Skris	X509_CINF *ci;
10855714Skris	ASN1_INTEGER *bs;
10955714Skris	EVP_PKEY *pkey=NULL;
11055714Skris	const char *neg;
11155714Skris	ASN1_STRING *str=NULL;
11255714Skris
113109998Smarkm	if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
114109998Smarkm			mlch = '\n';
115109998Smarkm			nmindent = 12;
116109998Smarkm	}
117109998Smarkm
118109998Smarkm	if(nmflags == X509_FLAG_COMPAT)
119109998Smarkm		nmindent = 16;
120109998Smarkm
12155714Skris	ci=x->cert_info;
122109998Smarkm	if(!(cflag & X509_FLAG_NO_HEADER))
12355714Skris		{
124109998Smarkm		if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err;
125109998Smarkm		if (BIO_write(bp,"    Data:\n",10) <= 0) goto err;
12655714Skris		}
127109998Smarkm	if(!(cflag & X509_FLAG_NO_VERSION))
12855714Skris		{
129109998Smarkm		l=X509_get_version(x);
130109998Smarkm		if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err;
131109998Smarkm		}
132109998Smarkm	if(!(cflag & X509_FLAG_NO_SERIAL))
133109998Smarkm		{
13455714Skris
135109998Smarkm		if (BIO_write(bp,"        Serial Number:",22) <= 0) goto err;
136109998Smarkm
137109998Smarkm		bs=X509_get_serialNumber(x);
138109998Smarkm		if (bs->length <= 4)
13955714Skris			{
140109998Smarkm			l=ASN1_INTEGER_get(bs);
141109998Smarkm			if (l < 0)
142109998Smarkm				{
143109998Smarkm				l= -l;
144109998Smarkm				neg="-";
145109998Smarkm				}
146109998Smarkm			else
147109998Smarkm				neg="";
148109998Smarkm			if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
14955714Skris				goto err;
15055714Skris			}
151109998Smarkm		else
152109998Smarkm			{
153109998Smarkm			neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
154109998Smarkm			if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err;
15555714Skris
156109998Smarkm			for (i=0; i<bs->length; i++)
157109998Smarkm				{
158109998Smarkm				if (BIO_printf(bp,"%02x%c",bs->data[i],
159109998Smarkm					((i+1 == bs->length)?'\n':':')) <= 0)
160109998Smarkm					goto err;
161109998Smarkm				}
162109998Smarkm			}
16355714Skris
164109998Smarkm		}
16555714Skris
166109998Smarkm	if(!(cflag & X509_FLAG_NO_SIGNAME))
16755714Skris		{
168109998Smarkm		if (BIO_printf(bp,"%8sSignature Algorithm: ","") <= 0)
169109998Smarkm			goto err;
170109998Smarkm		if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0)
171109998Smarkm			goto err;
172109998Smarkm		if (BIO_puts(bp, "\n") <= 0)
173109998Smarkm			goto err;
17455714Skris		}
175109998Smarkm
176109998Smarkm	if(!(cflag & X509_FLAG_NO_ISSUER))
17755714Skris		{
178109998Smarkm		if (BIO_printf(bp,"        Issuer:%c",mlch) <= 0) goto err;
179109998Smarkm		if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err;
180109998Smarkm		if (BIO_write(bp,"\n",1) <= 0) goto err;
18155714Skris		}
182109998Smarkm	if(!(cflag & X509_FLAG_NO_VALIDITY))
18355714Skris		{
184109998Smarkm		if (BIO_write(bp,"        Validity\n",17) <= 0) goto err;
185109998Smarkm		if (BIO_write(bp,"            Not Before: ",24) <= 0) goto err;
186109998Smarkm		if (!ASN1_TIME_print(bp,X509_get_notBefore(x))) goto err;
187109998Smarkm		if (BIO_write(bp,"\n            Not After : ",25) <= 0) goto err;
188109998Smarkm		if (!ASN1_TIME_print(bp,X509_get_notAfter(x))) goto err;
189109998Smarkm		if (BIO_write(bp,"\n",1) <= 0) goto err;
19055714Skris		}
191109998Smarkm	if(!(cflag & X509_FLAG_NO_SUBJECT))
192109998Smarkm		{
193109998Smarkm		if (BIO_printf(bp,"        Subject:%c",mlch) <= 0) goto err;
194109998Smarkm		if (X509_NAME_print_ex(bp,X509_get_subject_name(x),nmindent, nmflags) < 0) goto err;
195109998Smarkm		if (BIO_write(bp,"\n",1) <= 0) goto err;
196109998Smarkm		}
197109998Smarkm	if(!(cflag & X509_FLAG_NO_PUBKEY))
198109998Smarkm		{
199109998Smarkm		if (BIO_write(bp,"        Subject Public Key Info:\n",33) <= 0)
200109998Smarkm			goto err;
201109998Smarkm		if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0)
202109998Smarkm			goto err;
203109998Smarkm		if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
204109998Smarkm			goto err;
205109998Smarkm		if (BIO_puts(bp, "\n") <= 0)
206109998Smarkm			goto err;
20755714Skris
208109998Smarkm		pkey=X509_get_pubkey(x);
209109998Smarkm		if (pkey == NULL)
21055714Skris			{
211109998Smarkm			BIO_printf(bp,"%12sUnable to load Public Key\n","");
212109998Smarkm			ERR_print_errors(bp);
21355714Skris			}
214109998Smarkm		else
215109998Smarkm#ifndef OPENSSL_NO_RSA
216109998Smarkm		if (pkey->type == EVP_PKEY_RSA)
217109998Smarkm			{
218109998Smarkm			BIO_printf(bp,"%12sRSA Public Key: (%d bit)\n","",
219109998Smarkm			BN_num_bits(pkey->pkey.rsa->n));
220109998Smarkm			RSA_print(bp,pkey->pkey.rsa,16);
221109998Smarkm			}
222109998Smarkm		else
223109998Smarkm#endif
224109998Smarkm#ifndef OPENSSL_NO_DSA
225109998Smarkm		if (pkey->type == EVP_PKEY_DSA)
226109998Smarkm			{
227109998Smarkm			BIO_printf(bp,"%12sDSA Public Key:\n","");
228109998Smarkm			DSA_print(bp,pkey->pkey.dsa,16);
229109998Smarkm			}
230109998Smarkm		else
231109998Smarkm#endif
232109998Smarkm			BIO_printf(bp,"%12sUnknown Public Key:\n","");
233109998Smarkm
234109998Smarkm		EVP_PKEY_free(pkey);
23555714Skris		}
23655714Skris
237109998Smarkm	if (!(cflag & X509_FLAG_NO_EXTENSIONS))
238109998Smarkm		X509V3_extensions_print(bp, "X509v3 extensions",
239109998Smarkm					ci->extensions, cflag, 8);
24055714Skris
241109998Smarkm	if(!(cflag & X509_FLAG_NO_SIGDUMP))
24255714Skris		{
243109998Smarkm		if(X509_signature_print(bp, x->sig_alg, x->signature) <= 0) goto err;
24455714Skris		}
245109998Smarkm	if(!(cflag & X509_FLAG_NO_AUX))
246109998Smarkm		{
247109998Smarkm		if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err;
248109998Smarkm		}
24955714Skris	ret=1;
25055714Skriserr:
25155714Skris	if (str != NULL) ASN1_STRING_free(str);
25268651Skris	if (m != NULL) OPENSSL_free(m);
25355714Skris	return(ret);
25455714Skris	}
25555714Skris
256109998Smarkmint X509_ocspid_print (BIO *bp, X509 *x)
257109998Smarkm	{
258109998Smarkm	unsigned char *der=NULL ;
259109998Smarkm	unsigned char *dertmp;
260109998Smarkm	int derlen;
261109998Smarkm	int i;
262109998Smarkm	unsigned char SHA1md[SHA_DIGEST_LENGTH];
263109998Smarkm
264109998Smarkm	/* display the hash of the subject as it would appear
265109998Smarkm	   in OCSP requests */
266109998Smarkm	if (BIO_printf(bp,"        Subject OCSP hash: ") <= 0)
267109998Smarkm		goto err;
268109998Smarkm	derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
269109998Smarkm	if ((der = dertmp = (unsigned char *)OPENSSL_malloc (derlen)) == NULL)
270109998Smarkm		goto err;
271109998Smarkm	i2d_X509_NAME(x->cert_info->subject, &dertmp);
272109998Smarkm
273109998Smarkm	EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL);
274109998Smarkm	for (i=0; i < SHA_DIGEST_LENGTH; i++)
275109998Smarkm		{
276109998Smarkm		if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0) goto err;
277109998Smarkm		}
278109998Smarkm	OPENSSL_free (der);
279109998Smarkm	der=NULL;
280109998Smarkm
281109998Smarkm	/* display the hash of the public key as it would appear
282109998Smarkm	   in OCSP requests */
283109998Smarkm	if (BIO_printf(bp,"\n        Public key OCSP hash: ") <= 0)
284109998Smarkm		goto err;
285109998Smarkm
286109998Smarkm	EVP_Digest(x->cert_info->key->public_key->data,
287109998Smarkm		x->cert_info->key->public_key->length, SHA1md, NULL, EVP_sha1(), NULL);
288109998Smarkm	for (i=0; i < SHA_DIGEST_LENGTH; i++)
289109998Smarkm		{
290109998Smarkm		if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0)
291109998Smarkm			goto err;
292109998Smarkm		}
293109998Smarkm	BIO_printf(bp,"\n");
294109998Smarkm
295109998Smarkm	return (1);
296109998Smarkmerr:
297109998Smarkm	if (der != NULL) OPENSSL_free(der);
298109998Smarkm	return(0);
299109998Smarkm	}
300109998Smarkm
301109998Smarkmint X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
302109998Smarkm{
303109998Smarkm	unsigned char *s;
304109998Smarkm	int i, n;
305109998Smarkm	if (BIO_puts(bp,"    Signature Algorithm: ") <= 0) return 0;
306109998Smarkm	if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0;
307109998Smarkm
308109998Smarkm	n=sig->length;
309109998Smarkm	s=sig->data;
310109998Smarkm	for (i=0; i<n; i++)
311109998Smarkm		{
312109998Smarkm		if ((i%18) == 0)
313109998Smarkm			if (BIO_write(bp,"\n        ",9) <= 0) return 0;
314109998Smarkm			if (BIO_printf(bp,"%02x%s",s[i],
315109998Smarkm				((i+1) == n)?"":":") <= 0) return 0;
316109998Smarkm		}
317109998Smarkm	if (BIO_write(bp,"\n",1) != 1) return 0;
318109998Smarkm	return 1;
319109998Smarkm}
320109998Smarkm
32155714Skrisint ASN1_STRING_print(BIO *bp, ASN1_STRING *v)
32255714Skris	{
32355714Skris	int i,n;
32455714Skris	char buf[80],*p;;
32555714Skris
32655714Skris	if (v == NULL) return(0);
32755714Skris	n=0;
32855714Skris	p=(char *)v->data;
32955714Skris	for (i=0; i<v->length; i++)
33055714Skris		{
33155714Skris		if ((p[i] > '~') || ((p[i] < ' ') &&
33255714Skris			(p[i] != '\n') && (p[i] != '\r')))
33355714Skris			buf[n]='.';
33455714Skris		else
33555714Skris			buf[n]=p[i];
33655714Skris		n++;
33755714Skris		if (n >= 80)
33855714Skris			{
33955714Skris			if (BIO_write(bp,buf,n) <= 0)
34055714Skris				return(0);
34155714Skris			n=0;
34255714Skris			}
34355714Skris		}
34455714Skris	if (n > 0)
34555714Skris		if (BIO_write(bp,buf,n) <= 0)
34655714Skris			return(0);
34755714Skris	return(1);
34855714Skris	}
34955714Skris
35055714Skrisint ASN1_TIME_print(BIO *bp, ASN1_TIME *tm)
35155714Skris{
35255714Skris	if(tm->type == V_ASN1_UTCTIME) return ASN1_UTCTIME_print(bp, tm);
35355714Skris	if(tm->type == V_ASN1_GENERALIZEDTIME)
35455714Skris				return ASN1_GENERALIZEDTIME_print(bp, tm);
35555714Skris	BIO_write(bp,"Bad time value",14);
35655714Skris	return(0);
35755714Skris}
35855714Skris
35955714Skrisstatic const char *mon[12]=
36055714Skris    {
36155714Skris    "Jan","Feb","Mar","Apr","May","Jun",
36255714Skris    "Jul","Aug","Sep","Oct","Nov","Dec"
36355714Skris    };
36455714Skris
36555714Skrisint ASN1_GENERALIZEDTIME_print(BIO *bp, ASN1_GENERALIZEDTIME *tm)
36655714Skris	{
36755714Skris	char *v;
36855714Skris	int gmt=0;
36955714Skris	int i;
37055714Skris	int y=0,M=0,d=0,h=0,m=0,s=0;
37155714Skris
37255714Skris	i=tm->length;
37355714Skris	v=(char *)tm->data;
37455714Skris
37555714Skris	if (i < 12) goto err;
37655714Skris	if (v[i-1] == 'Z') gmt=1;
37755714Skris	for (i=0; i<12; i++)
37855714Skris		if ((v[i] > '9') || (v[i] < '0')) goto err;
37955714Skris	y= (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0');
38055714Skris	M= (v[4]-'0')*10+(v[5]-'0');
38155714Skris	if ((M > 12) || (M < 1)) goto err;
38255714Skris	d= (v[6]-'0')*10+(v[7]-'0');
38355714Skris	h= (v[8]-'0')*10+(v[9]-'0');
38455714Skris	m=  (v[10]-'0')*10+(v[11]-'0');
38555714Skris	if (	(v[12] >= '0') && (v[12] <= '9') &&
38655714Skris		(v[13] >= '0') && (v[13] <= '9'))
38755714Skris		s=  (v[12]-'0')*10+(v[13]-'0');
38855714Skris
38955714Skris	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s",
39055714Skris		mon[M-1],d,h,m,s,y,(gmt)?" GMT":"") <= 0)
39155714Skris		return(0);
39255714Skris	else
39355714Skris		return(1);
39455714Skriserr:
39555714Skris	BIO_write(bp,"Bad time value",14);
39655714Skris	return(0);
39755714Skris	}
39855714Skris
39955714Skrisint ASN1_UTCTIME_print(BIO *bp, ASN1_UTCTIME *tm)
40055714Skris	{
40155714Skris	char *v;
40255714Skris	int gmt=0;
40355714Skris	int i;
40455714Skris	int y=0,M=0,d=0,h=0,m=0,s=0;
40555714Skris
40655714Skris	i=tm->length;
40755714Skris	v=(char *)tm->data;
40855714Skris
40955714Skris	if (i < 10) goto err;
41055714Skris	if (v[i-1] == 'Z') gmt=1;
41155714Skris	for (i=0; i<10; i++)
41255714Skris		if ((v[i] > '9') || (v[i] < '0')) goto err;
41355714Skris	y= (v[0]-'0')*10+(v[1]-'0');
41455714Skris	if (y < 50) y+=100;
41555714Skris	M= (v[2]-'0')*10+(v[3]-'0');
41655714Skris	if ((M > 12) || (M < 1)) goto err;
41755714Skris	d= (v[4]-'0')*10+(v[5]-'0');
41855714Skris	h= (v[6]-'0')*10+(v[7]-'0');
41955714Skris	m=  (v[8]-'0')*10+(v[9]-'0');
42055714Skris	if (	(v[10] >= '0') && (v[10] <= '9') &&
42155714Skris		(v[11] >= '0') && (v[11] <= '9'))
42255714Skris		s=  (v[10]-'0')*10+(v[11]-'0');
42355714Skris
42455714Skris	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s",
42555714Skris		mon[M-1],d,h,m,s,y+1900,(gmt)?" GMT":"") <= 0)
42655714Skris		return(0);
42755714Skris	else
42855714Skris		return(1);
42955714Skriserr:
43055714Skris	BIO_write(bp,"Bad time value",14);
43155714Skris	return(0);
43255714Skris	}
43355714Skris
43455714Skrisint X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
43555714Skris	{
436109998Smarkm	char *s,*c,*b;
43755714Skris	int ret=0,l,ll,i,first=1;
43855714Skris
43955714Skris	ll=80-2-obase;
44055714Skris
441109998Smarkm	b=s=X509_NAME_oneline(name,NULL,0);
44279998Skris	if (!*s)
443109998Smarkm		{
444109998Smarkm		OPENSSL_free(b);
44579998Skris		return 1;
446109998Smarkm		}
44755714Skris	s++; /* skip the first slash */
44855714Skris
44955714Skris	l=ll;
45055714Skris	c=s;
45155714Skris	for (;;)
45255714Skris		{
45355714Skris#ifndef CHARSET_EBCDIC
45455714Skris		if (	((*s == '/') &&
45555714Skris				((s[1] >= 'A') && (s[1] <= 'Z') && (
45655714Skris					(s[2] == '=') ||
45755714Skris					((s[2] >= 'A') && (s[2] <= 'Z') &&
45855714Skris					(s[3] == '='))
45955714Skris				 ))) ||
46055714Skris			(*s == '\0'))
46155714Skris#else
46255714Skris		if (	((*s == '/') &&
46355714Skris				(isupper(s[1]) && (
46455714Skris					(s[2] == '=') ||
46555714Skris					(isupper(s[2]) &&
46655714Skris					(s[3] == '='))
46755714Skris				 ))) ||
46855714Skris			(*s == '\0'))
46955714Skris#endif
47055714Skris			{
47155714Skris			if ((l <= 0) && !first)
47255714Skris				{
47355714Skris				first=0;
47455714Skris				if (BIO_write(bp,"\n",1) != 1) goto err;
47555714Skris				for (i=0; i<obase; i++)
47655714Skris					{
47755714Skris					if (BIO_write(bp," ",1) != 1) goto err;
47855714Skris					}
47955714Skris				l=ll;
48055714Skris				}
48155714Skris			i=s-c;
48255714Skris			if (BIO_write(bp,c,i) != i) goto err;
48355714Skris			c+=i;
48455714Skris			c++;
48555714Skris			if (*s != '\0')
48655714Skris				{
48755714Skris				if (BIO_write(bp,", ",2) != 2) goto err;
48855714Skris				}
48955714Skris			l--;
49055714Skris			}
49155714Skris		if (*s == '\0') break;
49255714Skris		s++;
49355714Skris		l--;
49455714Skris		}
49555714Skris
49655714Skris	ret=1;
49755714Skris	if (0)
49855714Skris		{
49955714Skriserr:
50055714Skris		X509err(X509_F_X509_NAME_PRINT,ERR_R_BUF_LIB);
50155714Skris		}
502109998Smarkm	OPENSSL_free(b);
50355714Skris	return(ret);
50455714Skris	}
50555714Skris
506