mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-30 16:17:02 +01:00
common: Extend function percent_data_escape.
* common/percent.c (percent_data_escape): Add new args prefix and plus_escape. * agent/command.c (cmd_put_secret): Adjust for changed function * common/t-percent.c (test_percent_data_escape): Extend test for the prefix. (test_percent_data_escape_plus): new test for the plus escaping. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
fec75a3868
commit
055f8854d3
@ -2751,7 +2751,7 @@ cmd_put_secret (assuan_context_t ctx, char *line)
|
|||||||
* into a string. Instead of resorting to base64 encoding we use a
|
* into a string. Instead of resorting to base64 encoding we use a
|
||||||
* special percent escaping which only quoted the Nul and the
|
* special percent escaping which only quoted the Nul and the
|
||||||
* percent character. */
|
* percent character. */
|
||||||
string = percent_data_escape (value? value : valstr, valuelen);
|
string = percent_data_escape (0, NULL, value? value : valstr, valuelen);
|
||||||
if (!string)
|
if (!string)
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
|
@ -37,16 +37,16 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Create a newly alloced string from STRING with all spaces and
|
/* Create a newly alloced string from STRING with all spaces and
|
||||||
control characters converted to plus signs or %xx sequences. The
|
* control characters converted to plus signs or %xx sequences. The
|
||||||
function returns the new string or NULL in case of a malloc
|
* function returns the new string or NULL in case of a malloc
|
||||||
failure.
|
* failure.
|
||||||
|
*
|
||||||
Note that we also escape the quote character to work around a bug
|
* Note that this fucntion also escapes the quote character to work
|
||||||
in the mingw32 runtime which does not correctly handle command line
|
* around a bug in the mingw32 runtime which does not correctly handle
|
||||||
quoting. We correctly double the quote mark when calling a program
|
* command line quoting. We correctly double the quote mark when
|
||||||
(i.e. gpg-protect-tool), but the pre-main code does not notice the
|
* calling a program (i.e. gpg-protect-tool), but the pre-main code
|
||||||
double quote as an escaped quote. We do this also on POSIX systems
|
* does not notice the double quote as an escaped quote. We do this
|
||||||
for consistency. */
|
* also on POSIX systems for consistency. */
|
||||||
char *
|
char *
|
||||||
percent_plus_escape (const char *string)
|
percent_plus_escape (const char *string)
|
||||||
{
|
{
|
||||||
@ -87,19 +87,36 @@ percent_plus_escape (const char *string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Create a newly alloced string from (DATA,DATALEN) with embedded
|
/* Create a newly malloced string from (DATA,DATALEN) with embedded
|
||||||
* Nuls quoted as %00. The standard percent unescaping can be
|
* nuls quoted as %00. The standard percent unescaping can be used to
|
||||||
* used to reverse this encoding. */
|
* reverse this encoding. With PLUS_ESCAPE set plus-escaping (spaces
|
||||||
|
* are replaced by a '+') and escaping of characters with values less
|
||||||
|
* than 0x20 is used. If PREFIX is not NULL it will be prepended to
|
||||||
|
* the output in standard escape format; that is PLUS_ESCAPING is
|
||||||
|
* ignored for PREFIX. */
|
||||||
char *
|
char *
|
||||||
percent_data_escape (const void *data, size_t datalen)
|
percent_data_escape (int plus_escape, const char *prefix,
|
||||||
|
const void *data, size_t datalen)
|
||||||
{
|
{
|
||||||
char *buffer, *p;
|
char *buffer, *p;
|
||||||
const char *s;
|
const unsigned char *s;
|
||||||
size_t n, length;
|
size_t n;
|
||||||
|
size_t length = 1;
|
||||||
|
|
||||||
for (length=1, s=data, n=datalen; n; s++, n--)
|
if (prefix)
|
||||||
{
|
{
|
||||||
if (!*s || *s == '%')
|
for (s = prefix; *s; s++)
|
||||||
|
{
|
||||||
|
if (*s == '%' || *s < 0x20)
|
||||||
|
length += 3;
|
||||||
|
else
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (s=data, n=datalen; n; s++, n--)
|
||||||
|
{
|
||||||
|
if (!*s || *s == '%' || (plus_escape && (*s < ' ' || *s == '+')))
|
||||||
length += 3;
|
length += 3;
|
||||||
else
|
else
|
||||||
length++;
|
length++;
|
||||||
@ -109,6 +126,20 @@ percent_data_escape (const void *data, size_t datalen)
|
|||||||
if (!buffer)
|
if (!buffer)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (prefix)
|
||||||
|
{
|
||||||
|
for (s = prefix; *s; s++)
|
||||||
|
{
|
||||||
|
if (*s == '%' || *s < 0x20)
|
||||||
|
{
|
||||||
|
snprintf (p, 4, "%%%02X", *s);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*p++ = *s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (s=data, n=datalen; n; s++, n--)
|
for (s=data, n=datalen; n; s++, n--)
|
||||||
{
|
{
|
||||||
if (!*s)
|
if (!*s)
|
||||||
@ -121,13 +152,21 @@ percent_data_escape (const void *data, size_t datalen)
|
|||||||
memcpy (p, "%25", 3);
|
memcpy (p, "%25", 3);
|
||||||
p += 3;
|
p += 3;
|
||||||
}
|
}
|
||||||
|
else if (plus_escape && *s == ' ')
|
||||||
|
{
|
||||||
|
*p++ = '+';
|
||||||
|
}
|
||||||
|
else if (plus_escape && (*s < ' ' || *s == '+'))
|
||||||
|
{
|
||||||
|
snprintf (p, 4, "%%%02X", *s);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
*p++ = *s;
|
*p++ = *s;
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,6 +101,142 @@ test_percent_plus_escape (void)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
test_percent_data_escape (void)
|
test_percent_data_escape (void)
|
||||||
|
{
|
||||||
|
static struct {
|
||||||
|
const char *prefix;
|
||||||
|
const char *data;
|
||||||
|
size_t datalen;
|
||||||
|
const char *expect;
|
||||||
|
} tbl[] = {
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
"", 0,
|
||||||
|
""
|
||||||
|
}, {
|
||||||
|
NULL,
|
||||||
|
"a", 1,
|
||||||
|
"a",
|
||||||
|
}, {
|
||||||
|
NULL,
|
||||||
|
"%22", 3,
|
||||||
|
"%2522"
|
||||||
|
}, {
|
||||||
|
NULL,
|
||||||
|
"%%", 3,
|
||||||
|
"%25%25%00"
|
||||||
|
}, {
|
||||||
|
NULL,
|
||||||
|
"\n \0BC\t", 6,
|
||||||
|
"\n %00BC\t"
|
||||||
|
}, {
|
||||||
|
"",
|
||||||
|
"", 0,
|
||||||
|
""
|
||||||
|
}, {
|
||||||
|
"",
|
||||||
|
"a", 1,
|
||||||
|
"a",
|
||||||
|
}, {
|
||||||
|
"",
|
||||||
|
"%22", 3,
|
||||||
|
"%2522"
|
||||||
|
}, {
|
||||||
|
"",
|
||||||
|
"%%", 3,
|
||||||
|
"%25%25%00"
|
||||||
|
}, {
|
||||||
|
"",
|
||||||
|
"\n \0BC\t", 6,
|
||||||
|
"\n %00BC\t"
|
||||||
|
}, {
|
||||||
|
"a",
|
||||||
|
"", 0,
|
||||||
|
"a"
|
||||||
|
}, {
|
||||||
|
"a",
|
||||||
|
"a", 1,
|
||||||
|
"aa",
|
||||||
|
}, {
|
||||||
|
"a",
|
||||||
|
"%22", 3,
|
||||||
|
"a%2522"
|
||||||
|
}, {
|
||||||
|
"a",
|
||||||
|
"%%", 3,
|
||||||
|
"a%25%25%00"
|
||||||
|
}, {
|
||||||
|
"a",
|
||||||
|
"\n \0BC\t", 6,
|
||||||
|
"a\n %00BC\t"
|
||||||
|
}, {
|
||||||
|
" ",
|
||||||
|
"%%", 3,
|
||||||
|
" %25%25%00"
|
||||||
|
}, {
|
||||||
|
"+",
|
||||||
|
"%%", 3,
|
||||||
|
"+%25%25%00"
|
||||||
|
}, {
|
||||||
|
"%",
|
||||||
|
"%%", 3,
|
||||||
|
"%25%25%25%00"
|
||||||
|
}, {
|
||||||
|
"a b",
|
||||||
|
"%%", 3,
|
||||||
|
"a b%25%25%00"
|
||||||
|
}, {
|
||||||
|
"a%2Bb",
|
||||||
|
"%%", 3,
|
||||||
|
"a%252Bb%25%25%00"
|
||||||
|
}, {
|
||||||
|
"\n",
|
||||||
|
"%%", 3,
|
||||||
|
"%0A%25%25%00"
|
||||||
|
}, {
|
||||||
|
NULL,
|
||||||
|
NULL, 0,
|
||||||
|
NULL }
|
||||||
|
};
|
||||||
|
char *buf;
|
||||||
|
int i;
|
||||||
|
size_t len, prefixlen;
|
||||||
|
|
||||||
|
for (i=0; tbl[i].data; i++)
|
||||||
|
{
|
||||||
|
buf = percent_data_escape (0, tbl[i].prefix, tbl[i].data, tbl[i].datalen);
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "out of core: %s\n", strerror (errno));
|
||||||
|
exit (2);
|
||||||
|
}
|
||||||
|
if (strcmp (buf, tbl[i].expect))
|
||||||
|
{
|
||||||
|
fail (i);
|
||||||
|
}
|
||||||
|
len = percent_plus_unescape_inplace (buf, 0);
|
||||||
|
prefixlen = tbl[i].prefix? strlen (tbl[i].prefix) : 0;
|
||||||
|
if (len != tbl[i].datalen + prefixlen)
|
||||||
|
fail (i);
|
||||||
|
else if (tbl[i].prefix && memcmp (buf, tbl[i].prefix, prefixlen)
|
||||||
|
&& !(prefixlen == 1 && *tbl[i].prefix == '+' && *buf == ' '))
|
||||||
|
{
|
||||||
|
/* Note extra condition above handles the one test case
|
||||||
|
* which reverts a plus to a space due to the use of the
|
||||||
|
* plus-unescape fucntion also for the prefix part. */
|
||||||
|
fail (i);
|
||||||
|
}
|
||||||
|
else if (memcmp (buf+prefixlen, tbl[i].data, tbl[i].datalen))
|
||||||
|
{
|
||||||
|
fail (i);
|
||||||
|
}
|
||||||
|
xfree (buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_percent_data_escape_plus (void)
|
||||||
{
|
{
|
||||||
static struct {
|
static struct {
|
||||||
const char *data;
|
const char *data;
|
||||||
@ -121,7 +257,28 @@ test_percent_data_escape (void)
|
|||||||
"%25%25%00"
|
"%25%25%00"
|
||||||
}, {
|
}, {
|
||||||
"\n \0BC\t", 6,
|
"\n \0BC\t", 6,
|
||||||
"\n %00BC\t"
|
"%0A+%00BC%09"
|
||||||
|
}, {
|
||||||
|
" ", 1,
|
||||||
|
"+"
|
||||||
|
}, {
|
||||||
|
" ", 2,
|
||||||
|
"++"
|
||||||
|
}, {
|
||||||
|
"+ +", 3,
|
||||||
|
"%2B+%2B"
|
||||||
|
}, {
|
||||||
|
"\" \"", 3, /* Note: This function does not escape quotes. */
|
||||||
|
"\"+\""
|
||||||
|
}, {
|
||||||
|
"%22", 3,
|
||||||
|
"%2522"
|
||||||
|
}, {
|
||||||
|
"%% ", 3,
|
||||||
|
"%25%25+"
|
||||||
|
}, {
|
||||||
|
"\n ABC\t", 6,
|
||||||
|
"%0A+ABC%09"
|
||||||
}, { NULL, 0, NULL }
|
}, { NULL, 0, NULL }
|
||||||
};
|
};
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -130,14 +287,16 @@ test_percent_data_escape (void)
|
|||||||
|
|
||||||
for (i=0; tbl[i].data; i++)
|
for (i=0; tbl[i].data; i++)
|
||||||
{
|
{
|
||||||
buf = percent_data_escape (tbl[i].data, tbl[i].datalen);
|
buf = percent_data_escape (1, NULL, tbl[i].data, tbl[i].datalen);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "out of core: %s\n", strerror (errno));
|
fprintf (stderr, "out of core: %s\n", strerror (errno));
|
||||||
exit (2);
|
exit (2);
|
||||||
}
|
}
|
||||||
if (strcmp (buf, tbl[i].expect))
|
if (strcmp (buf, tbl[i].expect))
|
||||||
fail (i);
|
{
|
||||||
|
fail (i);
|
||||||
|
}
|
||||||
len = percent_plus_unescape_inplace (buf, 0);
|
len = percent_plus_unescape_inplace (buf, 0);
|
||||||
if (len != tbl[i].datalen)
|
if (len != tbl[i].datalen)
|
||||||
fail (i);
|
fail (i);
|
||||||
@ -148,16 +307,15 @@ test_percent_data_escape (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
/* FIXME: We escape_unescape is not tested - only
|
/* FIXME: escape_unescape is not tested - only percent_plus_unescape. */
|
||||||
percent_plus_unescape. */
|
|
||||||
test_percent_plus_escape ();
|
test_percent_plus_escape ();
|
||||||
test_percent_data_escape ();
|
test_percent_data_escape ();
|
||||||
|
test_percent_data_escape_plus ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,8 @@ char *hex2str_alloc (const char *hexstring, size_t *r_count);
|
|||||||
|
|
||||||
/*-- percent.c --*/
|
/*-- percent.c --*/
|
||||||
char *percent_plus_escape (const char *string);
|
char *percent_plus_escape (const char *string);
|
||||||
char *percent_data_escape (const void *data, size_t datalen);
|
char *percent_data_escape (int plus, const char *prefix,
|
||||||
|
const void *data, size_t datalen);
|
||||||
char *percent_plus_unescape (const char *string, int nulrepl);
|
char *percent_plus_unescape (const char *string, int nulrepl);
|
||||||
char *percent_unescape (const char *string, int nulrepl);
|
char *percent_unescape (const char *string, int nulrepl);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user