Hello community,

here is the log from the commit of package shim for openSUSE:Factory checked in 
at 2013-10-02 13:33:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/shim (Old)
 and      /work/SRC/openSUSE:Factory/.shim.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "shim"

Changes:
--------
--- /work/SRC/openSUSE:Factory/shim/shim.changes        2013-09-25 
17:20:28.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.shim.new/shim.changes   2013-10-02 
13:33:53.000000000 +0200
@@ -1,0 +2,9 @@
+Tue Oct  1 04:29:29 UTC 2013 - g...@suse.com
+
+- Add shim-netboot-fixes.patch to include upstream netboot fixes
+- Add shim-mokmanager-disable-gfx-console.patch to disable the
+  graphics console to avoid system hang on some machines
+- Add shim-bnc841426-silence-shim-protocols.patch to silence the
+  shim protocols (bnc#841426)
+
+-------------------------------------------------------------------

New:
----
  shim-bnc841426-silence-shim-protocols.patch
  shim-mokmanager-disable-gfx-console.patch
  shim-netboot-fixes.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ shim.spec ++++++
--- /var/tmp/diff_new_pack.m2SgPz/_old  2013-10-02 13:33:54.000000000 +0200
+++ /var/tmp/diff_new_pack.m2SgPz/_new  2013-10-02 13:33:54.000000000 +0200
@@ -58,6 +58,12 @@
 Patch8:         shim-bnc808106-correct-certcount.patch
 # PATCH-FIX-UPSTREAM shim-mokmanager-ui-revamp.patch g...@suse.com -- Revamp 
the MokManager UI
 Patch9:         shim-mokmanager-ui-revamp.patch
+# PATCH-FIX-UPSTREAM shim-netboot-fixes.patch g...@suse.com -- Upstream 
netboot fixes
+Patch10:        shim-netboot-fixes.patch
+# PATCH-FIX-UPSTREAM shim-mokmanager-disable-gfx-console.patch g...@suse.com 
-- Disable graphics console to avoid system hang on some machines
+Patch11:        shim-mokmanager-disable-gfx-console.patch
+# PATCH-FIX-UPSTREAM shim-bnc841426-silence-shim-protocols.patch bnc#841426 
g...@suse.com -- Silence the shim protocols to avoid system hang
+Patch12:        shim-bnc841426-silence-shim-protocols.patch
 BuildRequires:  gnu-efi >= 3.0t
 BuildRequires:  mozilla-nss-tools
 BuildRequires:  openssl >= 0.9.8
@@ -90,6 +96,9 @@
 %patch7 -p1
 %patch8 -p1
 %patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
 
 %build
 chmod +x "make-certs"

++++++ shim-bnc841426-silence-shim-protocols.patch ++++++
++++ 789 lines (skipped)

++++++ shim-mokmanager-disable-gfx-console.patch ++++++
>From c19cef4b4a61c82ba9a2c323659a20ec5d1d7ba2 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjo...@redhat.com>
Date: Thu, 26 Sep 2013 09:44:50 -0400
Subject: [PATCH] MokManager needs to disable the graphics console.

Without this patch, on some machines we never see MokManager's UI.  This
protocol has never (I think?) been officially published, and yet I still
have new hardware that needs it.

If you're looking for a reference, look at:

EdkCompatibilityPkg/Foundation/Protocol/ConsoleControl/ConsoleControl.c

in the edk2 tree from Tiano.

Signed-off-by: Peter Jones <pjo...@redhat.com>
---
 Makefile          |  2 +-
 MokManager.c      | 32 ++++++++++++++++++++++++++++++++
 console_control.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 console_control.h

diff --git a/Makefile b/Makefile
index 77f3e52..1e4aed8 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,7 @@ OBJS  = shim.o netboot.o cert.o dbx.o
 KEYS   = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key
 SOURCES        = shim.c shim.h netboot.c signature.h PeImage.h
 MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o
-MOK_SOURCES = MokManager.c shim.h PasswordCrypt.c PasswordCrypt.h 
crypt_blowfish.c crypt_blowfish.h
+MOK_SOURCES = MokManager.c shim.h console_control.h PasswordCrypt.c 
PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h
 FALLBACK_OBJS = fallback.o
 FALLBACK_SRCS = fallback.c
 
diff --git a/MokManager.c b/MokManager.c
index 604129f..01362f2 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -6,6 +6,7 @@
 #include "signature.h"
 #include "PeImage.h"
 #include "PasswordCrypt.h"
+#include "console_control.h"
 
 #include "include/console.h"
 #include "include/simple_file.h"
@@ -1741,6 +1742,34 @@ static EFI_STATUS check_mok_request(EFI_HANDLE 
image_handle)
        return EFI_SUCCESS;
 }
 
+static VOID setup_console (int text)
+{
+       EFI_STATUS status;
+       EFI_GUID console_control_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
+       EFI_CONSOLE_CONTROL_PROTOCOL *concon;
+       static EFI_CONSOLE_CONTROL_SCREEN_MODE mode =
+                                       EfiConsoleControlScreenGraphics;
+       EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode;
+
+       status = LibLocateProtocol(&console_control_guid, (VOID **)&concon);
+       if (status != EFI_SUCCESS)
+               return;
+
+       if (text) {
+               new_mode = EfiConsoleControlScreenText;
+
+               status = uefi_call_wrapper(concon->GetMode, 4, concon, &mode,
+                                               0, 0);
+               /* If that didn't work, assume it's graphics */
+               if (status != EFI_SUCCESS)
+                       mode = EfiConsoleControlScreenGraphics;
+       } else {
+               new_mode = mode;
+       }
+
+       uefi_call_wrapper(concon->SetMode, 2, concon, new_mode);
+}
+
 static EFI_STATUS setup_rand (void)
 {
        EFI_TIME time;
@@ -1772,9 +1801,12 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, 
EFI_SYSTEM_TABLE *systab)
 
        InitializeLib(image_handle, systab);
 
+       setup_console(1);
+
        setup_rand();
 
        efi_status = check_mok_request(image_handle);
 
+       setup_console(0);
        return efi_status;
 }
diff --git a/console_control.h b/console_control.h
new file mode 100644
index 0000000..5fb8a4a
--- /dev/null
+++ b/console_control.h
@@ -0,0 +1,44 @@
+#ifndef _SHIM_CONSOLE_CONTROL_H
+#define _SHIM_CONSOLE_CONTROL_H 1
+
+#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
+  { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} 
}
+
+typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL   EFI_CONSOLE_CONTROL_PROTOCOL;
+
+typedef enum {
+  EfiConsoleControlScreenText,
+  EfiConsoleControlScreenGraphics,
+  EfiConsoleControlScreenMaxValue
+} EFI_CONSOLE_CONTROL_SCREEN_MODE;
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) (
+  IN  EFI_CONSOLE_CONTROL_PROTOCOL      *This,
+  OUT EFI_CONSOLE_CONTROL_SCREEN_MODE   *Mode,
+  OUT BOOLEAN                           *GopUgaExists,  OPTIONAL  
+  OUT BOOLEAN                           *StdInLocked    OPTIONAL
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) (
+  IN  EFI_CONSOLE_CONTROL_PROTOCOL      *This,
+  IN  EFI_CONSOLE_CONTROL_SCREEN_MODE   Mode
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) (
+  IN  EFI_CONSOLE_CONTROL_PROTOCOL      *This,
+  IN CHAR16                             *Password
+  );
+
+struct _EFI_CONSOLE_CONTROL_PROTOCOL {
+  EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE           GetMode;
+  EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE           SetMode;
+  EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN        LockStdIn;
+};
+
+#endif /* _SHIM_CONSOLE_CONTROL_H */
-- 
1.8.1.4

++++++ shim-netboot-fixes.patch ++++++
>From 6bd858269e91b3966c569f5d18a6fd3932b65112 Mon Sep 17 00:00:00 2001
From: Steve Langasek <steve.langa...@canonical.com>
Date: Fri, 20 Sep 2013 11:29:23 -0500
Subject: [PATCH 1/7] Pass the right arguments to
 EFI_PXE_BASE_CODE_TFTP_READ_FILE

A wrong pointer was being passed to EFI_PXE_BASE_CODE_TFTP_READ_FILE,
preventing us from getting the file size back from the tftp call, ensuring
that we don't have enough information to properly secureboot-validate the
retrieved image.
---
 netboot.c | 4 ++--
 shim.c    | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/netboot.c b/netboot.c
index d569048..f7a6a1a 100644
--- a/netboot.c
+++ b/netboot.c
@@ -328,7 +328,7 @@ EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle)
        return rc;
 }
 
-EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINTN 
*bufsiz)
+EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 
*bufsiz)
 {
        EFI_STATUS rc;
        EFI_PXE_BASE_CODE_TFTP_OPCODE read = EFI_PXE_BASE_CODE_TFTP_READ_FILE;
@@ -346,7 +346,7 @@ EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID 
**buffer, UINTN *bufs
 
 try_again:
        rc = uefi_call_wrapper(pxe->Mtftp, 10, pxe, read, *buffer, overwrite,
-                               &bufsiz, &blksz, &tftp_addr, full_path, NULL, 
nobuffer);
+                               bufsiz, &blksz, &tftp_addr, full_path, NULL, 
nobuffer);
 
        if (rc == EFI_BUFFER_TOO_SMALL) {
                /* try again, doubling buf size */
diff --git a/shim.c b/shim.c
index 47e3812..c1bb85f 100644
--- a/shim.c
+++ b/shim.c
@@ -1193,7 +1193,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 
*ImagePath)
        EFI_DEVICE_PATH *path;
        CHAR16 *PathName = NULL;
        void *sourcebuffer = NULL;
-       UINTN sourcesize = 0;
+       UINT64 sourcesize = 0;
        void *data = NULL;
        int datasize;
 
-- 
1.8.1.4


>From b1fa932c45038fbe280420b88f0103610fff48aa Mon Sep 17 00:00:00 2001
From: Steve Langasek <steve.langa...@canonical.com>
Date: Fri, 20 Sep 2013 13:03:57 -0500
Subject: [PATCH 2/7] Fix nul termination errors in filenames passed to tftp

Fix various errors in the tftp string handling, to ensure we always have
properly nul-terminated strings.
---
 netboot.c | 39 ++++++++++++++++-----------------------
 1 file changed, 16 insertions(+), 23 deletions(-)

diff --git a/netboot.c b/netboot.c
index f7a6a1a..b31e71c 100644
--- a/netboot.c
+++ b/netboot.c
@@ -54,7 +54,7 @@ static inline unsigned short int __swap16(unsigned short int 
x)
 
 static EFI_PXE_BASE_CODE *pxe;
 static EFI_IP_ADDRESS tftp_addr;
-static char *full_path;
+static UINT8 *full_path;
 
 
 typedef struct {
@@ -112,7 +112,7 @@ try_again:
        for (i=0; i < (bs / sizeof(EFI_HANDLE)); i++) {
                status = uefi_call_wrapper(BS->OpenProtocol, 6, hbuf[i],
                                           &pxe_base_code_protocol,
-                                          &pxe, image_handle, NULL,
+                                          (void **)&pxe, image_handle, NULL,
                                           EFI_OPEN_PROTOCOL_GET_PROTOCOL);
 
                if (status != EFI_SUCCESS) {
@@ -228,15 +228,15 @@ static UINT8 *str2ip6(char *str)
 
 static BOOLEAN extract_tftp_info(char *url)
 {
-       char *start, *end;
+       CHAR8 *start, *end;
        char ip6str[128];
-       char *template = DEFAULT_LOADER;
+       CHAR8 *template = (CHAR8 *)DEFAULT_LOADER;
 
        if (strncmp((UINT8 *)url, (UINT8 *)"tftp://";, 7)) {
                Print(L"URLS MUST START WITH tftp://\n";);
                return FALSE;
        }
-       start = url + 7;
+       start = (CHAR8 *)url + 7;
        if (*start != '[') {
                Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
                return FALSE;
@@ -251,21 +251,19 @@ static BOOLEAN extract_tftp_info(char *url)
                Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
                return FALSE;
        }
-       *end = '\0';
        memset(ip6str, 0, 128);
-       memcpy(ip6str, start, strlen((UINT8 *)start));
-       *end = ']';
+       memcpy(ip6str, start, end + 1 - start);
        end++;
        memcpy(&tftp_addr.v6, str2ip6(ip6str), 16);
-       full_path = AllocatePool(strlen((UINT8 *)end)+strlen((UINT8 
*)template)+1);
+       full_path = AllocateZeroPool(strlen(end)+strlen(template)+1);
        if (!full_path)
                return FALSE;
-       memset(full_path, 0, strlen((UINT8 *)end)+strlen((UINT8 *)template));
-       memcpy(full_path, end, strlen((UINT8 *)end));
-       end = strrchr(full_path, '/');
+       memcpy(full_path, end, strlen(end));
+       end = (CHAR8 *)strrchr((char *)full_path, '/');
        if (!end)
-               end = full_path;
-       memcpy(end, template, strlen((UINT8 *)template));
+               end = (CHAR8 *)full_path;
+       memcpy(end, template, strlen(template));
+       end[strlen(template)] = '\0';
 
        return TRUE;
 }
@@ -286,20 +284,15 @@ static EFI_STATUS parseDhcp6()
 
 static EFI_STATUS parseDhcp4()
 {
-       char *template = DEFAULT_LOADER;
-       char *tmp;
-       int len = strlen((CHAR8 *)template);
+       CHAR8 *template = (CHAR8 *)DEFAULT_LOADER;
+       full_path = AllocateZeroPool(strlen(template)+1);
 
-       tmp = AllocatePool(len+1);
-
-       if (!tmp)
+       if (!full_path)
                return EFI_OUT_OF_RESOURCES;
 
-
        memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4);
 
-       memcpy(tmp, template, len+1);
-       full_path = tmp;
+       memcpy(full_path, template, strlen(template));
 
        /* Note we don't capture the filename option here because we know its 
shim.efi
         * We instead assume the filename at the end of the path is going to be 
grubx64.efi
-- 
1.8.1.4


>From a68d8233dcc76094813e5c235a80fb6c7ec6ad7c Mon Sep 17 00:00:00 2001
From: Steve Langasek <steve.langa...@canonical.com>
Date: Fri, 20 Sep 2013 17:06:33 -0500
Subject: [PATCH 3/7] Fix an off-by-one error

We don't need to add one because our end pointer is already off the end of
the string we want to copy.
---
 netboot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/netboot.c b/netboot.c
index b31e71c..15dbdf7 100644
--- a/netboot.c
+++ b/netboot.c
@@ -252,7 +252,7 @@ static BOOLEAN extract_tftp_info(char *url)
                return FALSE;
        }
        memset(ip6str, 0, 128);
-       memcpy(ip6str, start, end + 1 - start);
+       memcpy(ip6str, start, end - start);
        end++;
        memcpy(&tftp_addr.v6, str2ip6(ip6str), 16);
        full_path = AllocateZeroPool(strlen(end)+strlen(template)+1);
-- 
1.8.1.4


>From bbaa1df5dcc6570dc29544dbcc00353f925a1128 Mon Sep 17 00:00:00 2001
From: Steve Langasek <steve.langa...@canonical.com>
Date: Sun, 22 Sep 2013 22:21:49 -0700
Subject: [PATCH 4/7] Misc allocation cleanups

---
 netboot.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/netboot.c b/netboot.c
index 15dbdf7..c81e28e 100644
--- a/netboot.c
+++ b/netboot.c
@@ -160,10 +160,9 @@ static char 
*get_v6_bootfile_url(EFI_PXE_BASE_CODE_DHCPV6_PACKET *pkt)
                if (ntohs(option->OpCode) == 59) {
                        /* This is the bootfile url option */
                        urllen = ntohs(option->Length);
-                       url = AllocatePool(urllen+2);
+                       url = AllocateZeroPool(urllen+1);
                        if (!url)
                                return NULL;
-                       memset(url, 0, urllen+2);
                        memcpy(url, option->Data, urllen);
                        return url;
                }
@@ -275,10 +274,13 @@ static EFI_STATUS parseDhcp6()
 
 
        bootfile_url = get_v6_bootfile_url(packet);
-       if (extract_tftp_info(bootfile_url) == FALSE)
-               return EFI_NOT_FOUND;
        if (!bootfile_url)
                return EFI_NOT_FOUND;
+       if (extract_tftp_info(bootfile_url) == FALSE) {
+               FreePool(bootfile_url);
+               return EFI_NOT_FOUND;
+       }
+       FreePool(bootfile_url);
        return EFI_SUCCESS;
 }
 
-- 
1.8.1.4


>From 4b1e7425479a111553f1055757429249bc389d28 Mon Sep 17 00:00:00 2001
From: Steve Langasek <steve.langa...@canonical.com>
Date: Sun, 22 Sep 2013 22:25:47 -0700
Subject: [PATCH 5/7] More consistent types, fewer casts

---
 netboot.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/netboot.c b/netboot.c
index c81e28e..dab1f5c 100644
--- a/netboot.c
+++ b/netboot.c
@@ -142,11 +142,11 @@ try_again:
        return rc;
 }
 
-static char *get_v6_bootfile_url(EFI_PXE_BASE_CODE_DHCPV6_PACKET *pkt)
+static CHAR8 *get_v6_bootfile_url(EFI_PXE_BASE_CODE_DHCPV6_PACKET *pkt)
 {
        void *optr;
        EFI_DHCP6_PACKET_OPTION *option;
-       char *url;
+       CHAR8 *url;
        UINT32 urllen;
 
        optr = pkt->DhcpOptions;
@@ -225,7 +225,7 @@ static UINT8 *str2ip6(char *str)
         return (UINT8 *)ip;
 }
 
-static BOOLEAN extract_tftp_info(char *url)
+static BOOLEAN extract_tftp_info(CHAR8 *url)
 {
        CHAR8 *start, *end;
        char ip6str[128];
@@ -235,7 +235,7 @@ static BOOLEAN extract_tftp_info(char *url)
                Print(L"URLS MUST START WITH tftp://\n";);
                return FALSE;
        }
-       start = (CHAR8 *)url + 7;
+       start = url + 7;
        if (*start != '[') {
                Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
                return FALSE;
@@ -270,8 +270,7 @@ static BOOLEAN extract_tftp_info(char *url)
 static EFI_STATUS parseDhcp6()
 {
        EFI_PXE_BASE_CODE_DHCPV6_PACKET *packet = 
(EFI_PXE_BASE_CODE_DHCPV6_PACKET *)&pxe->Mode->DhcpAck.Raw;
-       char *bootfile_url;
-
+       CHAR8 *bootfile_url;
 
        bootfile_url = get_v6_bootfile_url(packet);
        if (!bootfile_url)
-- 
1.8.1.4


>From 12cd90c232301efe7d262a33c471a6af1282ae03 Mon Sep 17 00:00:00 2001
From: Steve Langasek <steve.langa...@canonical.com>
Date: Sun, 22 Sep 2013 22:45:26 -0700
Subject: [PATCH 6/7] Correct limits on the length of ipv6 addresses

The maximum length of a string representation of an ipv6 address is 39
characters (8 groups of 4 hex chars, with 7 colons in between).  So don't
allocate more room than this - and more importantly, don't blindly accept
strings from the server that are longer than our buffer...
---
 netboot.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/netboot.c b/netboot.c
index dab1f5c..61777a2 100644
--- a/netboot.c
+++ b/netboot.c
@@ -228,7 +228,7 @@ static UINT8 *str2ip6(char *str)
 static BOOLEAN extract_tftp_info(CHAR8 *url)
 {
        CHAR8 *start, *end;
-       char ip6str[128];
+       char ip6str[40];
        CHAR8 *template = (CHAR8 *)DEFAULT_LOADER;
 
        if (strncmp((UINT8 *)url, (UINT8 *)"tftp://";, 7)) {
@@ -245,12 +245,16 @@ static BOOLEAN extract_tftp_info(CHAR8 *url)
        end = start;
        while ((*end != '\0') && (*end != ']')) {
                end++;
+               if (end - start > 39) {
+                       Print(L"TFTP URL includes malformed IPv6 address\n");
+                       return FALSE;
+               }
        }
        if (end == '\0') {
                Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
                return FALSE;
        }
-       memset(ip6str, 0, 128);
+       memset(ip6str, 0, 40);
        memcpy(ip6str, start, end - start);
        end++;
        memcpy(&tftp_addr.v6, str2ip6(ip6str), 16);
-- 
1.8.1.4


>From 0c3bd9d9ea5261cfdf5c1d6feb2f42d17ba4ca8a Mon Sep 17 00:00:00 2001
From: Steve Langasek <steve.langa...@canonical.com>
Date: Sun, 22 Sep 2013 23:11:26 -0700
Subject: [PATCH 7/7] Fix a memory leak

---
 netboot.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/netboot.c b/netboot.c
index 61777a2..927445d 100644
--- a/netboot.c
+++ b/netboot.c
@@ -356,6 +356,8 @@ try_again:
                goto try_again;
        }
 
+       if (rc != EFI_SUCCESS && *buffer) {
+               FreePool(*buffer);
+       }
        return rc;
-
 }
-- 
1.8.1.4

-- 
To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org
For additional commands, e-mail: opensuse-commit+h...@opensuse.org

Reply via email to