mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Add function to extract the mailbox.
* g10/misc.c (has_invalid_email_chars, is_valid_mailbox) (is_valid_user_id): Move to ... * g10/mailbox.c: new file. (string_has_ctrl_or_space, has_dotdot_after_at): New. (has_invalid_email_chars): New. * g10/t-mailbox.c: New. * g10/Makefile.am (module_tests): Add t-mailbox. (t_mailbox_SOURCES, t_mailbox_LDADD): New. -- Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
d790111801
commit
93fa3d5c17
@ -83,6 +83,7 @@ common_source = \
|
||||
textfilter.c \
|
||||
progress.c \
|
||||
misc.c \
|
||||
mailbox.c \
|
||||
rmd160.c rmd160.h \
|
||||
options.h \
|
||||
openfile.c \
|
||||
@ -154,9 +155,11 @@ gpgv2_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
|
||||
gpgv2_LDFLAGS = $(extra_bin_ldflags)
|
||||
|
||||
t_common_ldadd =
|
||||
module_tests = t-rmd160
|
||||
module_tests = t-rmd160 t-mailbox
|
||||
t_rmd160_SOURCES = t-rmd160.c rmd160.c
|
||||
t_rmd160_LDADD = $(t_common_ldadd)
|
||||
t_mailbox_SOURCES = t-mailbox.c mailbox.c
|
||||
t_mailbox_LDADD = $(t_common_ldadd)
|
||||
|
||||
|
||||
$(PROGRAMS): $(needed_libs) ../common/libgpgrl.a
|
||||
|
184
g10/mailbox.c
Normal file
184
g10/mailbox.c
Normal file
@ -0,0 +1,184 @@
|
||||
/* mailbox.c - Mail address helper functions
|
||||
* Copyright (C) 1998-2010 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2014-2015 Werner Koch
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "gpg.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
static int
|
||||
string_count_chr (const char *string, int c)
|
||||
{
|
||||
int count;
|
||||
|
||||
for (count=0; *string; string++ )
|
||||
if ( *string == c )
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
string_has_ctrl_or_space (const char *string)
|
||||
{
|
||||
for (; *string; string++ )
|
||||
if (!(*string & 0x80) && *string <= 0x20)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if STRING has two consecutive '.' after an '@'
|
||||
sign. */
|
||||
static int
|
||||
has_dotdot_after_at (const char *string)
|
||||
{
|
||||
string = strchr (string, '@');
|
||||
if (!string)
|
||||
return 0; /* No at-sign. */
|
||||
string++;
|
||||
return !!strstr (string, "..");
|
||||
}
|
||||
|
||||
|
||||
/* Check whether the string has characters not valid in an RFC-822
|
||||
address. To cope with OpenPGP we ignore non-ascii characters
|
||||
so that for example umlauts are legal in an email address. An
|
||||
OpenPGP user ID must be utf-8 encoded but there is no strict
|
||||
requirement for RFC-822. Thus to avoid IDNA encoding we put the
|
||||
address verbatim as utf-8 into the user ID under the assumption
|
||||
that mail programs handle IDNA at a lower level and take OpenPGP
|
||||
user IDs as utf-8. Note that we can't do an utf-8 encoding
|
||||
checking here because in keygen.c this function is called with the
|
||||
native encoding and native to utf-8 encoding is only done later. */
|
||||
int
|
||||
has_invalid_email_chars (const char *s)
|
||||
{
|
||||
int at_seen=0;
|
||||
const char *valid_chars=
|
||||
"01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
for ( ; *s; s++ )
|
||||
{
|
||||
if ( (*s & 0x80) )
|
||||
continue; /* We only care about ASCII. */
|
||||
if ( *s == '@' )
|
||||
at_seen=1;
|
||||
else if ( !at_seen && !(strchr (valid_chars, *s)
|
||||
|| strchr ("!#$%&'*+/=?^`{|}~", *s)))
|
||||
return 1;
|
||||
else if ( at_seen && !strchr( valid_chars, *s ) )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether NAME represents a valid mailbox according to
|
||||
RFC822. Returns true if so. */
|
||||
int
|
||||
is_valid_mailbox (const char *name)
|
||||
{
|
||||
return !( !name
|
||||
|| !*name
|
||||
|| has_invalid_email_chars (name)
|
||||
|| string_count_chr (name,'@') != 1
|
||||
|| *name == '@'
|
||||
|| name[strlen(name)-1] == '@'
|
||||
|| name[strlen(name)-1] == '.'
|
||||
|| strstr (name, "..") );
|
||||
}
|
||||
|
||||
|
||||
/* Return the mailbox (local-part@domain) form a standard user id.
|
||||
Caller must free the result. Returns NULL if no valid mailbox was
|
||||
found (or we are out of memory). */
|
||||
char *
|
||||
mailbox_from_userid (const char *userid)
|
||||
{
|
||||
const char *s, *s_end;
|
||||
size_t len;
|
||||
char *result = NULL;
|
||||
|
||||
s = strchr (userid, '<');
|
||||
if (s)
|
||||
{
|
||||
/* Seems to be a standard user id. */
|
||||
s++;
|
||||
s_end = strchr (s, '>');
|
||||
if (s_end && s_end > s)
|
||||
{
|
||||
len = s_end - s;
|
||||
result = xtrymalloc (len + 1);
|
||||
if (!result)
|
||||
return NULL; /* Ooops - out of core. */
|
||||
strncpy (result, s, len);
|
||||
result[len] = 0;
|
||||
/* Apply some basic checks on the address. We do not use
|
||||
is_valid_mailbox because those checks are too strict. */
|
||||
if (string_count_chr (result, '@') != 1 /* Need exactly one '@. */
|
||||
|| *result == '@' /* local-part missing. */
|
||||
|| result[len-1] == '@' /* domain missing. */
|
||||
|| result[len-1] == '.' /* ends with a dot. */
|
||||
|| string_has_ctrl_or_space (result)
|
||||
|| has_dotdot_after_at (result))
|
||||
{
|
||||
xfree (result);
|
||||
result = NULL;
|
||||
errno = EINVAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
errno = EINVAL;
|
||||
}
|
||||
else if (is_valid_mailbox (userid))
|
||||
{
|
||||
/* The entire user id is a mailbox. Return that one. Note that
|
||||
this fallback method has some restrictions on the valid
|
||||
syntax of the mailbox. However, those who want weird
|
||||
addresses should know about it and use the regular <...>
|
||||
syntax. */
|
||||
result = xtrystrdup (userid);
|
||||
}
|
||||
else
|
||||
errno = EINVAL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether UID is a valid standard user id of the form
|
||||
"Heinrich Heine <heinrichh@duesseldorf.de>"
|
||||
and return true if this is the case. */
|
||||
int
|
||||
is_valid_user_id (const char *uid)
|
||||
{
|
||||
if (!uid || !*uid)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
10
g10/main.h
10
g10/main.h
@ -162,9 +162,6 @@ char *optsep(char **stringp);
|
||||
char *argsplit(char *string);
|
||||
int parse_options(char *str,unsigned int *options,
|
||||
struct parse_options *opts,int noisy);
|
||||
int has_invalid_email_chars (const char *s);
|
||||
int is_valid_mailbox (const char *name);
|
||||
int is_valid_user_id (const char *uid);
|
||||
const char *get_libexecdir (void);
|
||||
int path_access(const char *file,int mode);
|
||||
|
||||
@ -179,6 +176,13 @@ int mpi_print (estream_t stream, gcry_mpi_t a, int mode);
|
||||
unsigned int ecdsa_qbits_from_Q (unsigned int qbits);
|
||||
|
||||
|
||||
/*-- mailbox.c --*/
|
||||
int has_invalid_email_chars (const char *s);
|
||||
int is_valid_mailbox (const char *name);
|
||||
char *mailbox_from_userid (const char *userid);
|
||||
int is_valid_user_id (const char *uid);
|
||||
|
||||
|
||||
/*-- status.c --*/
|
||||
void set_status_fd ( int fd );
|
||||
int is_status_enabled ( void );
|
||||
|
75
g10/misc.c
75
g10/misc.c
@ -70,18 +70,6 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static int
|
||||
string_count_chr (const char *string, int c)
|
||||
{
|
||||
int count;
|
||||
|
||||
for (count=0; *string; string++ )
|
||||
if ( *string == c )
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ENABLE_SELINUX_HACKS
|
||||
/* A object and a global variable to keep track of files marked as
|
||||
@ -1464,69 +1452,6 @@ parse_options(char *str,unsigned int *options,
|
||||
}
|
||||
|
||||
|
||||
/* Check whether the string has characters not valid in an RFC-822
|
||||
address. To cope with OpenPGP we ignore non-ascii characters
|
||||
so that for example umlauts are legal in an email address. An
|
||||
OpenPGP user ID must be utf-8 encoded but there is no strict
|
||||
requirement for RFC-822. Thus to avoid IDNA encoding we put the
|
||||
address verbatim as utf-8 into the user ID under the assumption
|
||||
that mail programs handle IDNA at a lower level and take OpenPGP
|
||||
user IDs as utf-8. Note that we can't do an utf-8 encoding
|
||||
checking here because in keygen.c this function is called with the
|
||||
native encoding and native to utf-8 encoding is only done later. */
|
||||
int
|
||||
has_invalid_email_chars (const char *s)
|
||||
{
|
||||
int at_seen=0;
|
||||
const char *valid_chars=
|
||||
"01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
for ( ; *s; s++ )
|
||||
{
|
||||
if ( (*s & 0x80) )
|
||||
continue; /* We only care about ASCII. */
|
||||
if ( *s == '@' )
|
||||
at_seen=1;
|
||||
else if ( !at_seen && !(strchr (valid_chars, *s)
|
||||
|| strchr ("!#$%&'*+/=?^`{|}~", *s)))
|
||||
return 1;
|
||||
else if ( at_seen && !strchr( valid_chars, *s ) )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether NAME represents a valid mailbox according to
|
||||
RFC822. Returns true if so. */
|
||||
int
|
||||
is_valid_mailbox (const char *name)
|
||||
{
|
||||
return !( !name
|
||||
|| !*name
|
||||
|| has_invalid_email_chars (name)
|
||||
|| string_count_chr (name,'@') != 1
|
||||
|| *name == '@'
|
||||
|| name[strlen(name)-1] == '@'
|
||||
|| name[strlen(name)-1] == '.'
|
||||
|| strstr (name, "..") );
|
||||
}
|
||||
|
||||
|
||||
/* Check whether UID is a valid standard user id of the form
|
||||
"Heinrich Heine <heinrichh@duesseldorf.de>"
|
||||
and return true if this is the case. */
|
||||
int
|
||||
is_valid_user_id (const char *uid)
|
||||
{
|
||||
if (!uid || !*uid)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Similar to access(2), but uses PATH to find the file. */
|
||||
int
|
||||
path_access(const char *file,int mode)
|
||||
|
127
g10/t-mailbox.c
Normal file
127
g10/t-mailbox.c
Normal file
@ -0,0 +1,127 @@
|
||||
/* t-mailbox.c - Module test for mailbox.c
|
||||
* Copyright (C) 2015 Werner Koch
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gpg.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
|
||||
#define pass() do { ; } while(0)
|
||||
#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\
|
||||
__FILE__,__LINE__, (a)); \
|
||||
exit (1); \
|
||||
} while(0)
|
||||
|
||||
|
||||
void *
|
||||
gcry_malloc (size_t n)
|
||||
{
|
||||
return malloc (n);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
gcry_strdup (const char *string)
|
||||
{
|
||||
return strdup (string);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gcry_free (void *a)
|
||||
{
|
||||
if (a)
|
||||
free (a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
run_test (void)
|
||||
{
|
||||
static struct
|
||||
{
|
||||
const char *userid;
|
||||
const char *mbox;
|
||||
} testtbl[] =
|
||||
{
|
||||
{ "Werner Koch <wk@gnupg.org>", "wk@gnupg.org" },
|
||||
{ "<wk@gnupg.org>", "wk@gnupg.org" },
|
||||
{ "wk@gnupg.org", "wk@gnupg.org" },
|
||||
{ "wk@gnupg.org ", NULL },
|
||||
{ " wk@gnupg.org", NULL },
|
||||
{ "Werner Koch (test) <wk@gnupg.org>", "wk@gnupg.org" },
|
||||
{ "Werner Koch <wk@gnupg.org> (test)", "wk@gnupg.org" },
|
||||
{ "Werner Koch <wk@gnupg.org (test)", NULL },
|
||||
{ "Werner Koch <wk@gnupg.org >", NULL },
|
||||
{ "Werner Koch <wk@gnupg.org", NULL },
|
||||
{ "", NULL },
|
||||
{ "@", NULL },
|
||||
{ "bar <>", NULL },
|
||||
{ "<foo@example.org>", "foo@example.org" },
|
||||
{ "<foo.@example.org>", "foo.@example.org" },
|
||||
{ "<.foo.@example.org>", ".foo.@example.org" },
|
||||
{ "<foo..@example.org>", "foo..@example.org" },
|
||||
{ "<foo..bar@example.org>", "foo..bar@example.org" },
|
||||
{ "<foo@example.org.>", NULL },
|
||||
{ "<foo@example..org>", NULL },
|
||||
{ "<foo@.>", NULL },
|
||||
{ "<@example.org>", NULL },
|
||||
{ "<foo@@example.org>", NULL },
|
||||
{ "<@foo@example.org>", NULL },
|
||||
{ "<foo@example.org> ()", "foo@example.org" },
|
||||
{ "<fo()o@example.org> ()", "fo()o@example.org" },
|
||||
{ "<fo()o@example.org> ()", "fo()o@example.org" },
|
||||
{ "fo()o@example.org", NULL},
|
||||
{ "Mr. Foo <foo@example.org><bar@example.net>", "foo@example.org"},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
int idx;
|
||||
|
||||
for (idx=0; testtbl[idx].userid; idx++)
|
||||
{
|
||||
char *mbox = mailbox_from_userid (testtbl[idx].userid);
|
||||
|
||||
if (!testtbl[idx].mbox)
|
||||
{
|
||||
if (mbox)
|
||||
fail (idx);
|
||||
}
|
||||
else if (!mbox)
|
||||
fail (idx);
|
||||
else if (strcmp (mbox, testtbl[idx].mbox))
|
||||
fail (idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
run_test ();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user