• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/ap/gpl/timemachine/openssl-0.9.8e/crypto/objects/
1/* crypto/objects/obj_dat.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdio.h>
60#include <ctype.h>
61#include <limits.h>
62#include "cryptlib.h"
63#include <openssl/lhash.h>
64#include <openssl/asn1.h>
65#include <openssl/objects.h>
66
67/* obj_dat.h is generated from objects.h by obj_dat.pl */
68#ifndef OPENSSL_NO_OBJECT
69#include "obj_dat.h"
70#else
71/* You will have to load all the objects needed manually in the application */
72#define NUM_NID 0
73#define NUM_SN 0
74#define NUM_LN 0
75#define NUM_OBJ 0
76static unsigned char lvalues[1];
77static ASN1_OBJECT nid_objs[1];
78static ASN1_OBJECT *sn_objs[1];
79static ASN1_OBJECT *ln_objs[1];
80static ASN1_OBJECT *obj_objs[1];
81#endif
82
83static int sn_cmp(const void *a, const void *b);
84static int ln_cmp(const void *a, const void *b);
85static int obj_cmp(const void *a, const void *b);
86#define ADDED_DATA	0
87#define ADDED_SNAME	1
88#define ADDED_LNAME	2
89#define ADDED_NID	3
90
91typedef struct added_obj_st
92	{
93	int type;
94	ASN1_OBJECT *obj;
95	} ADDED_OBJ;
96
97static int new_nid=NUM_NID;
98static LHASH *added=NULL;
99
100static int sn_cmp(const void *a, const void *b)
101	{
102	const ASN1_OBJECT * const *ap = a, * const *bp = b;
103	return(strcmp((*ap)->sn,(*bp)->sn));
104	}
105
106static int ln_cmp(const void *a, const void *b)
107	{
108	const ASN1_OBJECT * const *ap = a, * const *bp = b;
109	return(strcmp((*ap)->ln,(*bp)->ln));
110	}
111
112/* static unsigned long add_hash(ADDED_OBJ *ca) */
113static unsigned long add_hash(const void *ca_void)
114	{
115	const ASN1_OBJECT *a;
116	int i;
117	unsigned long ret=0;
118	unsigned char *p;
119	const ADDED_OBJ *ca = (const ADDED_OBJ *)ca_void;
120
121	a=ca->obj;
122	switch (ca->type)
123		{
124	case ADDED_DATA:
125		ret=a->length<<20L;
126		p=(unsigned char *)a->data;
127		for (i=0; i<a->length; i++)
128			ret^=p[i]<<((i*3)%24);
129		break;
130	case ADDED_SNAME:
131		ret=lh_strhash(a->sn);
132		break;
133	case ADDED_LNAME:
134		ret=lh_strhash(a->ln);
135		break;
136	case ADDED_NID:
137		ret=a->nid;
138		break;
139	default:
140		/* abort(); */
141		return 0;
142		}
143	ret&=0x3fffffffL;
144	ret|=ca->type<<30L;
145	return(ret);
146	}
147
148/* static int add_cmp(ADDED_OBJ *ca, ADDED_OBJ *cb) */
149static int add_cmp(const void *ca_void, const void *cb_void)
150	{
151	ASN1_OBJECT *a,*b;
152	int i;
153	const ADDED_OBJ *ca = (const ADDED_OBJ *)ca_void;
154	const ADDED_OBJ *cb = (const ADDED_OBJ *)cb_void;
155
156	i=ca->type-cb->type;
157	if (i) return(i);
158	a=ca->obj;
159	b=cb->obj;
160	switch (ca->type)
161		{
162	case ADDED_DATA:
163		i=(a->length - b->length);
164		if (i) return(i);
165		return(memcmp(a->data,b->data,(size_t)a->length));
166	case ADDED_SNAME:
167		if (a->sn == NULL) return(-1);
168		else if (b->sn == NULL) return(1);
169		else return(strcmp(a->sn,b->sn));
170	case ADDED_LNAME:
171		if (a->ln == NULL) return(-1);
172		else if (b->ln == NULL) return(1);
173		else return(strcmp(a->ln,b->ln));
174	case ADDED_NID:
175		return(a->nid-b->nid);
176	default:
177		/* abort(); */
178		return 0;
179		}
180	}
181
182static int init_added(void)
183	{
184	if (added != NULL) return(1);
185	added=lh_new(add_hash,add_cmp);
186	return(added != NULL);
187	}
188
189static void cleanup1(ADDED_OBJ *a)
190	{
191	a->obj->nid=0;
192	a->obj->flags|=ASN1_OBJECT_FLAG_DYNAMIC|
193	                ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
194			ASN1_OBJECT_FLAG_DYNAMIC_DATA;
195	}
196
197static void cleanup2(ADDED_OBJ *a)
198	{ a->obj->nid++; }
199
200static void cleanup3(ADDED_OBJ *a)
201	{
202	if (--a->obj->nid == 0)
203		ASN1_OBJECT_free(a->obj);
204	OPENSSL_free(a);
205	}
206
207static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ *)
208static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ *)
209static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ *)
210
211void OBJ_cleanup(void)
212	{
213	if (added == NULL) return;
214	added->down_load=0;
215	lh_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */
216	lh_doall(added,LHASH_DOALL_FN(cleanup2)); /* set counters */
217	lh_doall(added,LHASH_DOALL_FN(cleanup3)); /* free objects */
218	lh_free(added);
219	added=NULL;
220	}
221
222int OBJ_new_nid(int num)
223	{
224	int i;
225
226	i=new_nid;
227	new_nid+=num;
228	return(i);
229	}
230
231int OBJ_add_object(const ASN1_OBJECT *obj)
232	{
233	ASN1_OBJECT *o;
234	ADDED_OBJ *ao[4]={NULL,NULL,NULL,NULL},*aop;
235	int i;
236
237	if (added == NULL)
238		if (!init_added()) return(0);
239	if ((o=OBJ_dup(obj)) == NULL) goto err;
240	if (!(ao[ADDED_NID]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
241	if ((o->length != 0) && (obj->data != NULL))
242		if (!(ao[ADDED_DATA]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
243	if (o->sn != NULL)
244		if (!(ao[ADDED_SNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
245	if (o->ln != NULL)
246		if (!(ao[ADDED_LNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err2;
247
248	for (i=ADDED_DATA; i<=ADDED_NID; i++)
249		{
250		if (ao[i] != NULL)
251			{
252			ao[i]->type=i;
253			ao[i]->obj=o;
254			aop=(ADDED_OBJ *)lh_insert(added,ao[i]);
255			/* memory leak, buit should not normally matter */
256			if (aop != NULL)
257				OPENSSL_free(aop);
258			}
259		}
260	o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
261			ASN1_OBJECT_FLAG_DYNAMIC_DATA);
262
263	return(o->nid);
264err2:
265	OBJerr(OBJ_F_OBJ_ADD_OBJECT,ERR_R_MALLOC_FAILURE);
266err:
267	for (i=ADDED_DATA; i<=ADDED_NID; i++)
268		if (ao[i] != NULL) OPENSSL_free(ao[i]);
269	if (o != NULL) OPENSSL_free(o);
270	return(NID_undef);
271	}
272
273ASN1_OBJECT *OBJ_nid2obj(int n)
274	{
275	ADDED_OBJ ad,*adp;
276	ASN1_OBJECT ob;
277
278	if ((n >= 0) && (n < NUM_NID))
279		{
280		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
281			{
282			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
283			return(NULL);
284			}
285		return((ASN1_OBJECT *)&(nid_objs[n]));
286		}
287	else if (added == NULL)
288		return(NULL);
289	else
290		{
291		ad.type=ADDED_NID;
292		ad.obj= &ob;
293		ob.nid=n;
294		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
295		if (adp != NULL)
296			return(adp->obj);
297		else
298			{
299			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
300			return(NULL);
301			}
302		}
303	}
304
305const char *OBJ_nid2sn(int n)
306	{
307	ADDED_OBJ ad,*adp;
308	ASN1_OBJECT ob;
309
310	if ((n >= 0) && (n < NUM_NID))
311		{
312		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
313			{
314			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
315			return(NULL);
316			}
317		return(nid_objs[n].sn);
318		}
319	else if (added == NULL)
320		return(NULL);
321	else
322		{
323		ad.type=ADDED_NID;
324		ad.obj= &ob;
325		ob.nid=n;
326		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
327		if (adp != NULL)
328			return(adp->obj->sn);
329		else
330			{
331			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
332			return(NULL);
333			}
334		}
335	}
336
337const char *OBJ_nid2ln(int n)
338	{
339	ADDED_OBJ ad,*adp;
340	ASN1_OBJECT ob;
341
342	if ((n >= 0) && (n < NUM_NID))
343		{
344		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
345			{
346			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
347			return(NULL);
348			}
349		return(nid_objs[n].ln);
350		}
351	else if (added == NULL)
352		return(NULL);
353	else
354		{
355		ad.type=ADDED_NID;
356		ad.obj= &ob;
357		ob.nid=n;
358		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
359		if (adp != NULL)
360			return(adp->obj->ln);
361		else
362			{
363			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
364			return(NULL);
365			}
366		}
367	}
368
369int OBJ_obj2nid(const ASN1_OBJECT *a)
370	{
371	ASN1_OBJECT **op;
372	ADDED_OBJ ad,*adp;
373
374	if (a == NULL)
375		return(NID_undef);
376	if (a->nid != 0)
377		return(a->nid);
378
379	if (added != NULL)
380		{
381		ad.type=ADDED_DATA;
382		ad.obj=(ASN1_OBJECT *)a; /* XXX: ugly but harmless */
383		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
384		if (adp != NULL) return (adp->obj->nid);
385		}
386	op=(ASN1_OBJECT **)OBJ_bsearch((const char *)&a,(const char *)obj_objs,
387		NUM_OBJ, sizeof(ASN1_OBJECT *),obj_cmp);
388	if (op == NULL)
389		return(NID_undef);
390	return((*op)->nid);
391	}
392
393/* Convert an object name into an ASN1_OBJECT
394 * if "noname" is not set then search for short and long names first.
395 * This will convert the "dotted" form into an object: unlike OBJ_txt2nid
396 * it can be used with any objects, not just registered ones.
397 */
398
399ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
400	{
401	int nid = NID_undef;
402	ASN1_OBJECT *op=NULL;
403	unsigned char *buf;
404	unsigned char *p;
405	const unsigned char *cp;
406	int i, j;
407
408	if(!no_name) {
409		if( ((nid = OBJ_sn2nid(s)) != NID_undef) ||
410			((nid = OBJ_ln2nid(s)) != NID_undef) )
411					return OBJ_nid2obj(nid);
412	}
413
414	/* Work out size of content octets */
415	i=a2d_ASN1_OBJECT(NULL,0,s,-1);
416	if (i <= 0) {
417		/* Don't clear the error */
418		/*ERR_clear_error();*/
419		return NULL;
420	}
421	/* Work out total size */
422	j = ASN1_object_size(0,i,V_ASN1_OBJECT);
423
424	if((buf=(unsigned char *)OPENSSL_malloc(j)) == NULL) return NULL;
425
426	p = buf;
427	/* Write out tag+length */
428	ASN1_put_object(&p,0,i,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
429	/* Write out contents */
430	a2d_ASN1_OBJECT(p,i,s,-1);
431
432	cp=buf;
433	op=d2i_ASN1_OBJECT(NULL,&cp,j);
434	OPENSSL_free(buf);
435	return op;
436	}
437
438int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
439{
440	int i,n=0,len,nid, first, use_bn;
441	BIGNUM *bl;
442	unsigned long l;
443	unsigned char *p;
444	char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
445
446	if ((a == NULL) || (a->data == NULL)) {
447		buf[0]='\0';
448		return(0);
449	}
450
451
452	if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
453		{
454		const char *s;
455		s=OBJ_nid2ln(nid);
456		if (s == NULL)
457			s=OBJ_nid2sn(nid);
458		if (buf)
459			BUF_strlcpy(buf,s,buf_len);
460		n=strlen(s);
461		return n;
462		}
463
464
465	len=a->length;
466	p=a->data;
467
468	first = 1;
469	bl = NULL;
470
471	while (len > 0)
472		{
473		l=0;
474		use_bn = 0;
475		for (;;)
476			{
477			unsigned char c = *p++;
478			len--;
479			if ((len == 0) && (c & 0x80))
480				goto err;
481			if (use_bn)
482				{
483				if (!BN_add_word(bl, c & 0x7f))
484					goto err;
485				}
486			else
487				l |= c  & 0x7f;
488			if (!(c & 0x80))
489				break;
490			if (!use_bn && (l > (ULONG_MAX >> 7L)))
491				{
492				if (!bl && !(bl = BN_new()))
493					goto err;
494				if (!BN_set_word(bl, l))
495					goto err;
496				use_bn = 1;
497				}
498			if (use_bn)
499				{
500				if (!BN_lshift(bl, bl, 7))
501					goto err;
502				}
503			else
504				l<<=7L;
505			}
506
507		if (first)
508			{
509			first = 0;
510			if (l >= 80)
511				{
512				i = 2;
513				if (use_bn)
514					{
515					if (!BN_sub_word(bl, 80))
516						goto err;
517					}
518				else
519					l -= 80;
520				}
521			else
522				{
523				i=(int)(l/40);
524				l-=(long)(i*40);
525				}
526			if (buf && (buf_len > 0))
527				{
528				*buf++ = i + '0';
529				buf_len--;
530				}
531			n++;
532			}
533
534		if (use_bn)
535			{
536			char *bndec;
537			bndec = BN_bn2dec(bl);
538			if (!bndec)
539				goto err;
540			i = strlen(bndec);
541			if (buf)
542				{
543				if (buf_len > 0)
544					{
545					*buf++ = '.';
546					buf_len--;
547					}
548				BUF_strlcpy(buf,bndec,buf_len);
549				if (i > buf_len)
550					{
551					buf += buf_len;
552					buf_len = 0;
553					}
554				else
555					{
556					buf+=i;
557					buf_len-=i;
558					}
559				}
560			n++;
561			n += i;
562			OPENSSL_free(bndec);
563			}
564		else
565			{
566			BIO_snprintf(tbuf,sizeof tbuf,".%lu",l);
567			i=strlen(tbuf);
568			if (buf && (buf_len > 0))
569				{
570				BUF_strlcpy(buf,tbuf,buf_len);
571				if (i > buf_len)
572					{
573					buf += buf_len;
574					buf_len = 0;
575					}
576				else
577					{
578					buf+=i;
579					buf_len-=i;
580					}
581				}
582			n+=i;
583			l=0;
584			}
585		}
586
587	if (bl)
588		BN_free(bl);
589	return n;
590
591	err:
592	if (bl)
593		BN_free(bl);
594	return -1;
595}
596
597int OBJ_txt2nid(const char *s)
598{
599	ASN1_OBJECT *obj;
600	int nid;
601	obj = OBJ_txt2obj(s, 0);
602	nid = OBJ_obj2nid(obj);
603	ASN1_OBJECT_free(obj);
604	return nid;
605}
606
607int OBJ_ln2nid(const char *s)
608	{
609	ASN1_OBJECT o,*oo= &o,**op;
610	ADDED_OBJ ad,*adp;
611
612	o.ln=s;
613	if (added != NULL)
614		{
615		ad.type=ADDED_LNAME;
616		ad.obj= &o;
617		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
618		if (adp != NULL) return (adp->obj->nid);
619		}
620	op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)ln_objs, NUM_LN,
621		sizeof(ASN1_OBJECT *),ln_cmp);
622	if (op == NULL) return(NID_undef);
623	return((*op)->nid);
624	}
625
626int OBJ_sn2nid(const char *s)
627	{
628	ASN1_OBJECT o,*oo= &o,**op;
629	ADDED_OBJ ad,*adp;
630
631	o.sn=s;
632	if (added != NULL)
633		{
634		ad.type=ADDED_SNAME;
635		ad.obj= &o;
636		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
637		if (adp != NULL) return (adp->obj->nid);
638		}
639	op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)sn_objs,NUM_SN,
640		sizeof(ASN1_OBJECT *),sn_cmp);
641	if (op == NULL) return(NID_undef);
642	return((*op)->nid);
643	}
644
645static int obj_cmp(const void *ap, const void *bp)
646	{
647	int j;
648	const ASN1_OBJECT *a= *(ASN1_OBJECT * const *)ap;
649	const ASN1_OBJECT *b= *(ASN1_OBJECT * const *)bp;
650
651	j=(a->length - b->length);
652        if (j) return(j);
653	return(memcmp(a->data,b->data,a->length));
654        }
655
656const char *OBJ_bsearch(const char *key, const char *base, int num, int size,
657	int (*cmp)(const void *, const void *))
658	{
659	return OBJ_bsearch_ex(key, base, num, size, cmp, 0);
660	}
661
662const char *OBJ_bsearch_ex(const char *key, const char *base, int num,
663	int size, int (*cmp)(const void *, const void *), int flags)
664	{
665	int l,h,i=0,c=0;
666	const char *p = NULL;
667
668	if (num == 0) return(NULL);
669	l=0;
670	h=num;
671	while (l < h)
672		{
673		i=(l+h)/2;
674		p= &(base[i*size]);
675		c=(*cmp)(key,p);
676		if (c < 0)
677			h=i;
678		else if (c > 0)
679			l=i+1;
680		else
681			break;
682		}
683#ifdef CHARSET_EBCDIC
684/* THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and
685 * I don't have perl (yet), we revert to a *LINEAR* search
686 * when the object wasn't found in the binary search.
687 */
688	if (c != 0)
689		{
690		for (i=0; i<num; ++i)
691			{
692			p= &(base[i*size]);
693			c = (*cmp)(key,p);
694			if (c == 0 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
695				return p;
696			}
697		}
698#endif
699	if (c != 0 && !(flags & OBJ_BSEARCH_VALUE_ON_NOMATCH))
700		p = NULL;
701	else if (c == 0 && (flags & OBJ_BSEARCH_FIRST_VALUE_ON_MATCH))
702		{
703		while(i > 0 && (*cmp)(key,&(base[(i-1)*size])) == 0)
704			i--;
705		p = &(base[i*size]);
706		}
707	return(p);
708	}
709
710int OBJ_create_objects(BIO *in)
711	{
712	MS_STATIC char buf[512];
713	int i,num=0;
714	char *o,*s,*l=NULL;
715
716	for (;;)
717		{
718		s=o=NULL;
719		i=BIO_gets(in,buf,512);
720		if (i <= 0) return(num);
721		buf[i-1]='\0';
722		if (!isalnum((unsigned char)buf[0])) return(num);
723		o=s=buf;
724		while (isdigit((unsigned char)*s) || (*s == '.'))
725			s++;
726		if (*s != '\0')
727			{
728			*(s++)='\0';
729			while (isspace((unsigned char)*s))
730				s++;
731			if (*s == '\0')
732				s=NULL;
733			else
734				{
735				l=s;
736				while ((*l != '\0') && !isspace((unsigned char)*l))
737					l++;
738				if (*l != '\0')
739					{
740					*(l++)='\0';
741					while (isspace((unsigned char)*l))
742						l++;
743					if (*l == '\0') l=NULL;
744					}
745				else
746					l=NULL;
747				}
748			}
749		else
750			s=NULL;
751		if ((o == NULL) || (*o == '\0')) return(num);
752		if (!OBJ_create(o,s,l)) return(num);
753		num++;
754		}
755	/* return(num); */
756	}
757
758int OBJ_create(const char *oid, const char *sn, const char *ln)
759	{
760	int ok=0;
761	ASN1_OBJECT *op=NULL;
762	unsigned char *buf;
763	int i;
764
765	i=a2d_ASN1_OBJECT(NULL,0,oid,-1);
766	if (i <= 0) return(0);
767
768	if ((buf=(unsigned char *)OPENSSL_malloc(i)) == NULL)
769		{
770		OBJerr(OBJ_F_OBJ_CREATE,ERR_R_MALLOC_FAILURE);
771		return(0);
772		}
773	i=a2d_ASN1_OBJECT(buf,i,oid,-1);
774	if (i == 0)
775		goto err;
776	op=(ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1),buf,i,sn,ln);
777	if (op == NULL)
778		goto err;
779	ok=OBJ_add_object(op);
780err:
781	ASN1_OBJECT_free(op);
782	OPENSSL_free(buf);
783	return(ok);
784	}
785
786