From 90dadf57cd0bf3b56535e4290583abcb2fca00e0 Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Wed, 8 Jun 2011 06:19:16 +0200 Subject: [PATCH] Fix IPv6 address handling in v3 extensions --- lib/x509v3ext.cpp | 53 +++++++++++++++++++++++++++++++++-------------- widgets/v3ext.cpp | 32 +++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/lib/x509v3ext.cpp b/lib/x509v3ext.cpp index 95cc37af..177d4296 100644 --- a/lib/x509v3ext.cpp +++ b/lib/x509v3ext.cpp @@ -196,6 +196,42 @@ static bool asn1TypePrintable(int type) return false; } +static QString ipv6_from_binary(const unsigned char *p) +{ + QString ip; + int i, skip =0, skiplen = 0, skippos =0; + + /* find largest gap */ + for (i = 0; i < 17; i += 2) { + if (i==16 || (p[i] | p[i +1])) { + if (skiplen < skip) { + skiplen = skip; + skippos = i - skip; + } + skip = 0; + } else { + skip += 2; + } + } + for (i = 0, skip = 0; i < 16; i += 2) { + int x = p[i] << 8 | p[i+1]; + skip += skippos == i; + switch (!x*4 + skip) { + case 5: // skip first 0 + skip = 2; + ip += ":"; + case 6: // skip next 0 + break; + default: // no reduction + skip = 0; + ip += QString("%1%2").arg(i? ":" : "").arg(x,0,16); + } + } + if (skip == 2) + ip += ":"; + return ip; +} + static bool genName2conf(GENERAL_NAME *gen, QString tag, QString *single, QString *sect) { @@ -222,22 +258,7 @@ genName2conf(GENERAL_NAME *gen, QString tag, QString *single, QString *sect) arg(p[0]).arg(p[1]).arg(p[2]).arg(p[3]); return true; } else if(gen->d.ip->length == 16) { - int skip = 0; - *single = "IP"; - for (int i = 0; i < 8; i++, p+=2) { - int x = p[0] << 8 | p[1]; - switch (!x*4 + skip) { - case 4: // start reduction - *single += QString(":"); - skip = 1; - case 5: // skip repeated 0 - break; - case 1: // end of reduction - skip = 2; - default: - *single += QString(":%1").arg(x,0,16); - } - } + *single = "IP:" + ipv6_from_binary(gen->d.ip->data); return true; } return false; diff --git a/widgets/v3ext.cpp b/widgets/v3ext.cpp index e16a1dd8..a94ef18e 100644 --- a/widgets/v3ext.cpp +++ b/widgets/v3ext.cpp @@ -16,6 +16,36 @@ #include "MainWindow.h" #include "lib/exception.h" + +// Complex regular expressions. + +#define BYTE_DEC "(?:25[0-5]|2[0-4]\\d|1\\d\\d|\\d{1,2})" +#define IPV4_ADDR "(?:(?:" BYTE_DEC "\\.){3}" BYTE_DEC ")" +#define SHORT_HEX "[0-9a-fA-F]{1,4}" +#define IPV6_FORM0 "(?:(?:" SHORT_HEX ":){7}" SHORT_HEX ")" +#define IPV6_FORM1 "(?::(?::" SHORT_HEX "){1,7})" +#define IPV6_FORM2 "(?:" SHORT_HEX ":(?::" SHORT_HEX "){1,6})" +#define IPV6_FORM3 "(?:(?:" SHORT_HEX ":){2}(?::" SHORT_HEX "){1,5})" +#define IPV6_FORM4 "(?:(?:" SHORT_HEX ":){3}(?::" SHORT_HEX "){1,4})" +#define IPV6_FORM5 "(?:(?:" SHORT_HEX ":){4}(?::" SHORT_HEX "){1,3})" +#define IPV6_FORM6 "(?:(?:" SHORT_HEX ":){5}(?::" SHORT_HEX "){1,2})" +#define IPV6_FORM7 "(?:(?:" SHORT_HEX ":){6}:" SHORT_HEX ")" +#define IPV6_FORM8 "(?:(?:" SHORT_HEX ":){7}:)" +#define IPV6_FORM9 "(?:::)" +#define IPV6_V4_0 "(?:(?:" SHORT_HEX ":){6}" IPV4_ADDR ")" +#define IPV6_V4_1 "(?::(?::" SHORT_HEX "){0,5}:" IPV4_ADDR ")" +#define IPV6_V4_2 "(?:" SHORT_HEX ":(?::" SHORT_HEX "){0,4}:" IPV4_ADDR ")" +#define IPV6_V4_3 "(?:(?:" SHORT_HEX ":){2}(?::" SHORT_HEX "){0,3}:" IPV4_ADDR ")" +#define IPV6_V4_4 "(?:(?:" SHORT_HEX ":){3}(?::" SHORT_HEX "){0,2}:" IPV4_ADDR ")" +#define IPV6_V4_5 "(?:(?:" SHORT_HEX ":){4}(?::" SHORT_HEX ")?:" IPV4_ADDR ")" +#define IPV6_V4_6 "(?:(?:" SHORT_HEX ":){5}:" IPV4_ADDR ")" +#define IPV6_ADDR "(?:" IPV6_FORM0 "|" IPV6_FORM1 "|" IPV6_FORM2 "|" \ + IPV6_FORM3 "|" IPV6_FORM4 "|" IPV6_FORM5 "|" \ + IPV6_FORM6 "|" IPV6_FORM7 "|" IPV6_FORM8 "|" \ + IPV6_FORM9 "|" IPV6_V4_0 "|" IPV6_V4_1 "|" \ + IPV6_V4_2 "|" IPV6_V4_3 "|" IPV6_V4_4 "|" \ + IPV6_V4_5 "|" IPV6_V4_6 ")" + v3ext::v3ext(QWidget *parent) :QDialog(parent) { @@ -74,7 +104,7 @@ void v3ext::setupLineEdit(const QString &s, QLineEdit *l) tt = tr("a DNS domain name"); } else if (s == "IP") { tt = tr("an IP address"); - QRegExp rx("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"); + QRegExp rx(IPV4_ADDR "|" IPV6_ADDR); v = new QRegExpValidator(rx, this); } else if (s == "otherName") { tt = tr("Syntax: ;TYPE:text like '1.2.3.4:UTF8:name'");