提交 4e5d3a7f 编写于 作者: D Dr. Stephen Henson

IPv6 display and input support for extensions usingh GeneralName.

上级 379e5689
...@@ -4,6 +4,12 @@ ...@@ -4,6 +4,12 @@
Changes between 0.9.7 and 0.9.8 [xx XXX xxxx] Changes between 0.9.7 and 0.9.8 [xx XXX xxxx]
*) IPv6 support for certificate extensions. The various extensions
which use the IP:a.b.c.d can now take IPv6 addresses using the
formats of RFC1884 2.2 . IPv6 addresses are now also displayed
correctly.
[Steve Henson]
*) Added an ENGINE that implements RSA by performing private key *) Added an ENGINE that implements RSA by performing private key
exponentiations with the GMP library. The conversions to and from exponentiations with the GMP library. The conversions to and from
GMP's mpz_t format aren't optimised nor are any montgomery forms GMP's mpz_t format aren't optimised nor are any montgomery forms
......
/* v3_alt.c */ /* v3_alt.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
* project 1999. * project.
*/ */
/* ==================================================================== /* ====================================================================
* Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -100,7 +100,8 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, ...@@ -100,7 +100,8 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret) GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
{ {
unsigned char *p; unsigned char *p;
char oline[256]; char oline[256], htmp[5];
int i;
switch (gen->type) switch (gen->type)
{ {
case GEN_OTHERNAME: case GEN_OTHERNAME:
...@@ -134,12 +135,25 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, ...@@ -134,12 +135,25 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
case GEN_IPADD: case GEN_IPADD:
p = gen->d.ip->data; p = gen->d.ip->data;
/* BUG: doesn't support IPV6 */ if(gen->d.ip->length == 4)
if(gen->d.ip->length != 4) { sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
else if(gen->d.ip->length == 16)
{
oline[0] = 0;
for (i = 0; i < 8; i++)
{
sprintf(htmp, "%X", p[0] << 8 | p[1]);
p += 2;
strcat(oline, htmp);
if (i != 7)
strcat(oline, ":");
}
}
else
{
X509V3_add_value("IP Address","<invalid>", &ret); X509V3_add_value("IP Address","<invalid>", &ret);
break; break;
} }
sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
X509V3_add_value("IP Address",oline, &ret); X509V3_add_value("IP Address",oline, &ret);
break; break;
...@@ -154,6 +168,7 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, ...@@ -154,6 +168,7 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
{ {
unsigned char *p; unsigned char *p;
int i;
switch (gen->type) switch (gen->type)
{ {
case GEN_OTHERNAME: case GEN_OTHERNAME:
...@@ -188,12 +203,24 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) ...@@ -188,12 +203,24 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
case GEN_IPADD: case GEN_IPADD:
p = gen->d.ip->data; p = gen->d.ip->data;
/* BUG: doesn't support IPV6 */ if(gen->d.ip->length == 4)
if(gen->d.ip->length != 4) { BIO_printf(out, "IP Address:%d.%d.%d.%d",
p[0], p[1], p[2], p[3]);
else if(gen->d.ip->length == 16)
{
BIO_printf(out, "IP Address");
for (i = 0; i < 8; i++)
{
BIO_printf(out, ":%X", p[0] << 8 | p[1]);
p += 2;
}
BIO_puts(out, "\n");
}
else
{
BIO_printf(out,"IP Address:<invalid>"); BIO_printf(out,"IP Address:<invalid>");
break; break;
} }
BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
break; break;
case GEN_RID: case GEN_RID:
...@@ -418,21 +445,12 @@ if(!name_cmp(name, "email")) { ...@@ -418,21 +445,12 @@ if(!name_cmp(name, "email")) {
gen->d.rid = obj; gen->d.rid = obj;
type = GEN_RID; type = GEN_RID;
} else if(!name_cmp(name, "IP")) { } else if(!name_cmp(name, "IP")) {
int i1,i2,i3,i4; if(!(gen->d.ip = a2i_IPADDRESS(value)))
unsigned char ip[4]; {
if((sscanf(value, "%d.%d.%d.%d",&i1,&i2,&i3,&i4) != 4) ||
(i1 < 0) || (i1 > 255) || (i2 < 0) || (i2 > 255) ||
(i3 < 0) || (i3 > 255) || (i4 < 0) || (i4 > 255) ) {
X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS); X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS);
ERR_add_error_data(2, "value=", value); ERR_add_error_data(2, "value=", value);
goto err; goto err;
} }
ip[0] = i1; ip[1] = i2 ; ip[2] = i3 ; ip[3] = i4;
if(!(gen->d.ip = M_ASN1_OCTET_STRING_new()) ||
!ASN1_STRING_set(gen->d.ip, ip, 4)) {
X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
goto err;
}
type = GEN_IPADD; type = GEN_IPADD;
} else if(!name_cmp(name, "otherName")) { } else if(!name_cmp(name, "otherName")) {
if (!do_othername(gen, value, ctx)) if (!do_othername(gen, value, ctx))
......
/* v3_utl.c */ /* v3_utl.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
* project 1999. * project.
*/ */
/* ==================================================================== /* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved. * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -70,6 +70,11 @@ static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens); ...@@ -70,6 +70,11 @@ static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens);
static void str_free(void *str); static void str_free(void *str);
static int append_ia5(STACK **sk, ASN1_IA5STRING *email); static int append_ia5(STACK **sk, ASN1_IA5STRING *email);
static int ipv4_from_asc(unsigned char *v4, const char *in);
static int ipv6_from_asc(unsigned char *v6, const char *in);
static int ipv6_cb(const char *elem, int len, void *usr);
static int ipv6_hex(unsigned char *out, const char *in, int inlen);
/* Add a CONF_VALUE name value pair to stack */ /* Add a CONF_VALUE name value pair to stack */
int X509V3_add_value(const char *name, const char *value, int X509V3_add_value(const char *name, const char *value,
...@@ -534,3 +539,204 @@ void X509_email_free(STACK *sk) ...@@ -534,3 +539,204 @@ void X509_email_free(STACK *sk)
{ {
sk_pop_free(sk, str_free); sk_pop_free(sk, str_free);
} }
/* Convert IP addresses both IPv4 and IPv6 into an
* OCTET STRING compatible with RFC3280.
*/
ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
{
unsigned char ipout[16];
ASN1_OCTET_STRING *ret;
int iplen;
/* If string contains a ':' assume IPv6 */
if (strchr(ipasc, ':'))
{
if (!ipv6_from_asc(ipout, ipasc))
return NULL;
iplen = 16;
}
else
{
if (!ipv4_from_asc(ipout, ipasc))
return NULL;
iplen = 4;
}
ret = ASN1_OCTET_STRING_new();
if (!ret)
return NULL;
if (!ASN1_OCTET_STRING_set(ret, ipout, iplen))
{
ASN1_OCTET_STRING_free(ret);
return NULL;
}
return ret;
}
static int ipv4_from_asc(unsigned char *v4, const char *in)
{
int a0, a1, a2, a3;
if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
return 0;
if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
|| (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
return 0;
v4[0] = a0;
v4[1] = a1;
v4[2] = a2;
v4[3] = a3;
return 1;
}
typedef struct {
/* Temporary store for IPV6 output */
unsigned char tmp[16];
/* Total number of bytes in tmp */
int total;
/* The position of a zero (corresponding to '::') */
int zero_pos;
/* Number of zeroes */
int zero_cnt;
} IPV6_STAT;
static int ipv6_from_asc(unsigned char *v6, const char *in)
{
IPV6_STAT v6stat;
v6stat.total = 0;
v6stat.zero_pos = -1;
v6stat.zero_cnt = 0;
/* Treat the IPv6 representation as a list of values
* separated by ':'. The presence of a '::' will parse
* as one, two or three zero length elements.
*/
if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
return 0;
/* Now for some sanity checks */
if (v6stat.zero_pos == -1)
{
/* If no '::' must have exactly 16 bytes */
if (v6stat.total != 16)
return 0;
}
else
{
/* If '::' must have less than 16 bytes */
if (v6stat.total == 16)
return 0;
/* More than three zeroes is an error */
if (v6stat.zero_cnt > 3)
return 0;
/* Can only have three zeroes if nothing else present */
else if (v6stat.zero_cnt == 3)
{
if (v6stat.total > 0)
return 0;
}
/* Can only have two zeroes if at start or end */
else if (v6stat.zero_cnt == 2)
{
if ((v6stat.zero_pos != 0)
&& (v6stat.zero_pos != v6stat.total))
return 0;
}
else
/* Can only have one zero if *not* start or end */
{
if ((v6stat.zero_pos == 0)
|| (v6stat.zero_pos == v6stat.total))
return 0;
}
}
/* Format result */
/* Copy initial part */
if (v6stat.zero_pos > 0)
memcpy(v6, v6stat.tmp, v6stat.zero_pos);
/* Zero middle */
if (v6stat.total != 16)
memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
/* Copy final part */
if (v6stat.total != v6stat.zero_pos)
memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
v6stat.tmp + v6stat.zero_pos,
v6stat.total - v6stat.zero_pos);
return 1;
}
static int ipv6_cb(const char *elem, int len, void *usr)
{
IPV6_STAT *s = usr;
/* Error if 16 bytes written */
if (s->total == 16)
return 0;
if (len == 0)
{
/* Zero length element, corresponds to '::' */
if (s->zero_pos == -1)
s->zero_pos = s->total;
/* If we've already got a :: its an error */
else if (s->zero_pos != s->total)
return 0;
s->zero_cnt++;
}
else
{
/* If more than 4 characters could be final a.b.c.d form */
if (len > 4)
{
/* Need at least 4 bytes left */
if (s->total > 12)
return 0;
/* Must be end of string */
if (elem[len])
return 0;
if (!ipv4_from_asc(s->tmp + s->total, elem))
return 0;
s->total += 4;
}
else
{
if (!ipv6_hex(s->tmp + s->total, elem, len))
return 0;
s->total += 2;
}
}
return 1;
}
/* Convert a string of up to 4 hex digits into the corresponding
* IPv6 form.
*/
static int ipv6_hex(unsigned char *out, const char *in, int inlen)
{
unsigned char c;
unsigned int num = 0;
if (inlen > 4)
return 0;
while(inlen--)
{
c = *in++;
num <<= 4;
if ((c >= '0') && (c <= '9'))
num |= c - '0';
else if ((c >= 'A') && (c <= 'F'))
num |= c - 'A' + 10;
else if ((c >= 'a') && (c <= 'f'))
num |= c - 'a' + 10;
else
return 0;
}
out[0] = num >> 8;
out[1] = num & 0xff;
return 1;
}
...@@ -547,6 +547,7 @@ STACK *X509_get1_email(X509 *x); ...@@ -547,6 +547,7 @@ STACK *X509_get1_email(X509 *x);
STACK *X509_REQ_get1_email(X509_REQ *x); STACK *X509_REQ_get1_email(X509_REQ *x);
void X509_email_free(STACK *sk); void X509_email_free(STACK *sk);
ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
/* BEGIN ERROR CODES */ /* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes /* The following lines are auto generated by the script mkerr.pl. Any changes
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册