From 9913253610bac69e9503800e85696491e018e327 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 25 Feb 2015 11:43:50 +0100 Subject: Move new mailbox.c source file to common/. * g10/mailbox.c: Move to ... * common/mbox-util.c: new file. * common/mbox-util.h: New. Include where needed. * g10/t-mailbox.c: Move to ... * common/t-mbox-util.c: new file. -- This will make it easier to use the code by other modules in common/. --- common/Makefile.am | 4 +- common/mbox-util.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++ common/mbox-util.h | 38 ++++++++++ common/t-mbox-util.c | 103 +++++++++++++++++++++++++++ g10/Makefile.am | 5 +- g10/getkey.c | 2 +- g10/keygen.c | 1 + g10/keylist.c | 2 + g10/mailbox.c | 184 ------------------------------------------------ g10/main.h | 7 -- g10/mainproc.c | 1 + g10/t-mailbox.c | 127 --------------------------------- 12 files changed, 343 insertions(+), 324 deletions(-) create mode 100644 common/mbox-util.c create mode 100644 common/mbox-util.h create mode 100644 common/t-mbox-util.c delete mode 100644 g10/mailbox.c delete mode 100644 g10/t-mailbox.c diff --git a/common/Makefile.am b/common/Makefile.am index 6b410624a..df2dafe46 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -75,6 +75,7 @@ common_sources = \ b64enc.c b64dec.c zb32.c \ convert.c \ percent.c \ + mbox-util.c mbox-util.h \ miscellaneous.c \ xasprintf.c \ xreadline.c \ @@ -177,7 +178,7 @@ jnlib_tests += t-w32-reg endif module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil \ t-session-env t-openpgp-oid t-ssh-utils t-dns-cert \ - t-mapstrings t-zb32 + t-mapstrings t-zb32 t-mbox-util if !HAVE_W32CE_SYSTEM module_tests += t-exechelp endif @@ -223,6 +224,7 @@ t_ssh_utils_LDADD = $(t_common_ldadd) t_dns_cert_LDADD = $(t_common_ldadd) $(DNSLIBS) t_mapstrings_LDADD = $(t_common_ldadd) t_zb32_LDADD = $(t_common_ldadd) +t_mbox_util_LDADD = $(t_common_ldadd) # http tests t_http_SOURCES = t-http.c diff --git a/common/mbox-util.c b/common/mbox-util.c new file mode 100644 index 000000000..332f62fa8 --- /dev/null +++ b/common/mbox-util.c @@ -0,0 +1,193 @@ +/* mbox-util.c - Mail address helper functions + * Copyright (C) 1998-2010 Free Software Foundation, Inc. + * Copyright (C) 1998-2015 Werner Koch + * + * This file is part of GnuPG. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either + * + * - the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * or + * + * - the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * or both in parallel, as here. + * + * This file 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 . + */ + +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "mbox-util.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 " + and return true if this is the case. */ +int +is_valid_user_id (const char *uid) +{ + if (!uid || !*uid) + return 0; + + return 1; +} diff --git a/common/mbox-util.h b/common/mbox-util.h new file mode 100644 index 000000000..b9a3bda6b --- /dev/null +++ b/common/mbox-util.h @@ -0,0 +1,38 @@ +/* mbox-util.h - Defs for mail address helper functions + * Copyright (C) 2015 Werner Koch + * + * This file is part of GnuPG. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either + * + * - the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * or + * + * - the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * or both in parallel, as here. + * + * This file 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 . + */ +#ifndef GNUPG_COMMON_MBOX_UTIL_H +#define GNUPG_COMMON_MBOX_UTIL_H + +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); + + +#endif /*GNUPG_COMMON_MBOX_UTIL_H*/ diff --git a/common/t-mbox-util.c b/common/t-mbox-util.c new file mode 100644 index 000000000..dfa4ada2a --- /dev/null +++ b/common/t-mbox-util.c @@ -0,0 +1,103 @@ +/* t-mbox-util.c - Module test for mbox-util.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 . + */ + +#include +#include +#include +#include + +#include "util.h" +#include "mbox-util.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) + + +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 ", NULL }, + { " wk@gnupg.org", NULL }, + { "Werner Koch (test) ", "wk@gnupg.org" }, + { "Werner Koch (test)", "wk@gnupg.org" }, + { "Werner Koch ", NULL }, + { "Werner Koch ", NULL }, + { "", "foo@example.org" }, + { "", "foo.@example.org" }, + { "<.foo.@example.org>", ".foo.@example.org" }, + { "", "foo..@example.org" }, + { "", "foo..bar@example.org" }, + { "", NULL }, + { "", NULL }, + { "", NULL }, + { "<@example.org>", NULL }, + { "", NULL }, + { "<@foo@example.org>", NULL }, + { " ()", "foo@example.org" }, + { " ()", "fo()o@example.org" }, + { " ()", "fo()o@example.org" }, + { "fo()o@example.org", NULL}, + { "Mr. Foo ", "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; +} diff --git a/g10/Makefile.am b/g10/Makefile.am index 070492406..0a021195a 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -83,7 +83,6 @@ common_source = \ textfilter.c \ progress.c \ misc.c \ - mailbox.c \ rmd160.c rmd160.h \ options.h \ openfile.c \ @@ -155,11 +154,9 @@ gpgv2_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \ gpgv2_LDFLAGS = $(extra_bin_ldflags) t_common_ldadd = -module_tests = t-rmd160 t-mailbox +module_tests = t-rmd160 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 diff --git a/g10/getkey.c b/g10/getkey.c index 116753c82..2a2448462 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -37,7 +37,7 @@ #include "keyserver-internal.h" #include "call-agent.h" #include "host2net.h" - +#include "mbox-util.h" #define MAX_PK_CACHE_ENTRIES PK_UID_CACHE_SIZE #define MAX_UID_CACHE_ENTRIES PK_UID_CACHE_SIZE diff --git a/g10/keygen.c b/g10/keygen.c index 11bfbd436..769e193f2 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -44,6 +44,7 @@ #include "pkglue.h" #include "../common/shareddefs.h" #include "host2net.h" +#include "mbox-util.h" /* The default algorithms. If you change them remember to change them diff --git a/g10/keylist.c b/g10/keylist.c index 881ffa474..7f13d8bdf 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -42,6 +42,8 @@ #include "i18n.h" #include "status.h" #include "call-agent.h" +#include "mbox-util.h" + static void list_all (int, int); static void list_one (strlist_t names, int secret, int mark_secret); diff --git a/g10/mailbox.c b/g10/mailbox.c deleted file mode 100644 index 64b818f37..000000000 --- a/g10/mailbox.c +++ /dev/null @@ -1,184 +0,0 @@ -/* 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 . - */ - -#include -#include -#include -#include -#include -#include - -#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 " - and return true if this is the case. */ -int -is_valid_user_id (const char *uid) -{ - if (!uid || !*uid) - return 0; - - return 1; -} diff --git a/g10/main.h b/g10/main.h index 8c326f645..39a1feb94 100644 --- a/g10/main.h +++ b/g10/main.h @@ -176,13 +176,6 @@ 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 ); diff --git a/g10/mainproc.c b/g10/mainproc.c index e0dba13e0..753fdbedd 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -39,6 +39,7 @@ #include "keyserver-internal.h" #include "photoid.h" #include "pka.h" +#include "mbox-util.h" /* Put an upper limit on nested packets. The 32 is an arbitrary diff --git a/g10/t-mailbox.c b/g10/t-mailbox.c deleted file mode 100644 index aa7cf3399..000000000 --- a/g10/t-mailbox.c +++ /dev/null @@ -1,127 +0,0 @@ -/* 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 . - */ - -#include -#include -#include -#include - -#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 ", NULL }, - { " wk@gnupg.org", NULL }, - { "Werner Koch (test) ", "wk@gnupg.org" }, - { "Werner Koch (test)", "wk@gnupg.org" }, - { "Werner Koch ", NULL }, - { "Werner Koch ", NULL }, - { "", "foo@example.org" }, - { "", "foo.@example.org" }, - { "<.foo.@example.org>", ".foo.@example.org" }, - { "", "foo..@example.org" }, - { "", "foo..bar@example.org" }, - { "", NULL }, - { "", NULL }, - { "", NULL }, - { "<@example.org>", NULL }, - { "", NULL }, - { "<@foo@example.org>", NULL }, - { " ()", "foo@example.org" }, - { " ()", "fo()o@example.org" }, - { " ()", "fo()o@example.org" }, - { "fo()o@example.org", NULL}, - { "Mr. Foo ", "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; -} -- cgit v1.2.3