The branch, v3-3-test has been updated
       via  6d5b415c5a0d7e0b7aae2f20ee7989ca58ec2f81 (commit)
       via  adc22887e50b6bb48f7235361460f61999965f84 (commit)
       via  513d7cf7dd8758045ba7666785dbada88a990ce1 (commit)
       via  d54fb8838a418493ebc7a559af4be95def97dfd9 (commit)
      from  6118aaeb2d4b164c5ed213aa2ae25ed13bfe1c22 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-3-test


- Log -----------------------------------------------------------------
commit 6d5b415c5a0d7e0b7aae2f20ee7989ca58ec2f81
Author: Stefan Metzmacher <[email protected]>
Date:   Thu Dec 18 15:02:42 2008 +0100

    s3:cluster: register the client connection via CTDB_CONTROL_TCP_ADD
    
    This means we correctly pass IPv6 addresses too.
    (CTDB_CONTROL_TCP_CLIENT was IPv4 only)
    
    metze
    (cherry picked from commit 465176b7e2fc1370dded850a80a8fe8519e79db8)

commit adc22887e50b6bb48f7235361460f61999965f84
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Dec 15 19:28:27 2008 +0100

    s3:pdb_tdb: store the next rid counter in passdb.tdb instead of 
winbind_idmap.tdb
    
    This upgrades the TDBSAM_VERSION to 4 and SAMU_BUFFER_V4.
    
    metze
    (cherry picked from commit 7516ba860c160e8b971b6f5bc1036370169e6e8a)

commit 513d7cf7dd8758045ba7666785dbada88a990ce1
Author: Stefan Metzmacher <[email protected]>
Date:   Tue Dec 16 11:51:14 2008 +0100

    s3:passdb: add SAMU_BUFFER_V4 with no changes
    
    The upgrade is required because of the followin TDBSAM_VERSION
    upgrade.
    
    metze
    (cherry picked from commit 671469ae7e3013809fe3995ec8f33dda9adda2ed)

commit d54fb8838a418493ebc7a559af4be95def97dfd9
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Dec 15 18:46:37 2008 +0100

    s3:passdb: make marshalling struct samu from and to a buffer more generic
    
    This marshalling isn't specific to tdbsam and it's
    ugly to have the related functions in two different files.
    
    metze
    (cherry picked from commit 0544734309feea44e8d449737a9934231f63693d)

-----------------------------------------------------------------------

Summary of changes:
 source/include/ctdbd_conn.h |    4 +-
 source/include/passdb.h     |   10 +-
 source/include/proto.h      |    6 +-
 source/lib/ctdbd_conn.c     |   26 +-
 source/passdb/passdb.c      |  682 ++++++++++++++++++++++++++++++++++++-
 source/passdb/pdb_tdb.c     |  788 ++++---------------------------------------
 source/smbd/server.c        |    9 +-
 7 files changed, 770 insertions(+), 755 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/include/ctdbd_conn.h b/source/include/ctdbd_conn.h
index 39f50c2..44c3516 100644
--- a/source/include/ctdbd_conn.h
+++ b/source/include/ctdbd_conn.h
@@ -57,8 +57,8 @@ NTSTATUS ctdbd_traverse(uint32 db_id,
                        void *private_data);
 
 NTSTATUS ctdbd_register_ips(struct ctdbd_connection *conn,
-                           const struct sockaddr_in *server,
-                           const struct sockaddr_in *client,
+                           const struct sockaddr *server,
+                           const struct sockaddr *client,
                            void (*release_ip_handler)(const char *ip_addr,
                                                       void *private_data),
                            void *private_data);
diff --git a/source/include/passdb.h b/source/include/passdb.h
index 744b723..93c1e3f 100644
--- a/source/include/passdb.h
+++ b/source/include/passdb.h
@@ -95,7 +95,15 @@ typedef struct logon_cache_struct {
        uint16 bad_password_count;
        time_t bad_password_time;
 } LOGIN_CACHE;
-               
+
+#define SAMU_BUFFER_V0         0
+#define SAMU_BUFFER_V1         1
+#define SAMU_BUFFER_V2         2
+#define SAMU_BUFFER_V3         3
+/* nothing changed from V3 to V4 */
+#define SAMU_BUFFER_V4         4
+#define SAMU_BUFFER_LATEST     SAMU_BUFFER_V4
+
 struct samu {
        struct pdb_methods *methods;
 
diff --git a/source/include/proto.h b/source/include/proto.h
index cc8e740..76e0d76 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -6175,8 +6175,9 @@ NTSTATUS local_password_change(const char *user_name,
                                const char *new_passwd, 
                                char **pp_err_str,
                                char **pp_msg_str);
-bool init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen);
-uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, bool 
size_only);
+bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
+                          uint8 *buf, uint32 buflen);
+uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool 
size_only);
 bool pdb_copy_sam_account(struct samu *dst, struct samu *src );
 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated);
 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated);
@@ -10222,7 +10223,6 @@ void init_sec_ctx(void);
 
 int smbd_server_fd(void);
 int get_client_fd(void);
-int client_get_tcp_info(struct sockaddr_in *server, struct sockaddr_in 
*client);
 struct event_context *smbd_event_context(void);
 struct messaging_context *smbd_messaging_context(void);
 struct memcache *smbd_memcache(void);
diff --git a/source/lib/ctdbd_conn.c b/source/lib/ctdbd_conn.c
index 1ae23bc..424c316 100644
--- a/source/lib/ctdbd_conn.c
+++ b/source/lib/ctdbd_conn.c
@@ -1175,13 +1175,13 @@ NTSTATUS ctdbd_traverse(uint32 db_id,
  */
 
 NTSTATUS ctdbd_register_ips(struct ctdbd_connection *conn,
-                           const struct sockaddr_in *server,
-                           const struct sockaddr_in *client,
+                           const struct sockaddr *server,
+                           const struct sockaddr *client,
                            void (*release_ip_handler)(const char *ip_addr,
                                                       void *private_data),
                            void *private_data)
 {
-       struct ctdb_control_tcp p;
+       struct ctdb_control_tcp_vnn p;
        TDB_DATA data;
        NTSTATUS status;
 
@@ -1190,6 +1190,21 @@ NTSTATUS ctdbd_register_ips(struct ctdbd_connection 
*conn,
         */
        SMB_ASSERT(conn->release_ip_handler == NULL);
 
+       switch (client->sa_family) {
+       case AF_INET:
+               p.dest.ip = *(struct sockaddr_in *)server;
+               p.src.ip = *(struct sockaddr_in *)client;
+               break;
+#ifdef HAVE_IPV6
+       case AF_INET6:
+               p.dest.ip6 = *(struct sockaddr_in6 *)server;
+               p.src.ip6 = *(struct sockaddr_in6 *)client;
+               break;
+#endif
+       default:
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
        conn->release_ip_handler = release_ip_handler;
 
        /*
@@ -1201,9 +1216,6 @@ NTSTATUS ctdbd_register_ips(struct ctdbd_connection *conn,
                return status;
        }
 
-       p.dest = *server;
-       p.src = *client;
-
        /*
         * inform ctdb of our tcp connection, so if IP takeover happens ctdb
         * can send an extra ack to trigger a reset for our client, so it
@@ -1213,7 +1225,7 @@ NTSTATUS ctdbd_register_ips(struct ctdbd_connection *conn,
        data.dsize = sizeof(p);
 
        return ctdbd_control(conn, CTDB_CURRENT_NODE, 
-                            CTDB_CONTROL_TCP_CLIENT, 0,
+                            CTDB_CONTROL_TCP_ADD, 0,
                             CTDB_CTRL_FLAG_NOREPLY, data, NULL, NULL, NULL);
 }
 
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c
index 7b50093..7d04cc0 100644
--- a/source/passdb/passdb.c
+++ b/source/passdb/passdb.c
@@ -856,12 +856,625 @@ NTSTATUS local_password_change(const char *user_name,
  Marshall/unmarshall struct samu structs.
  *********************************************************************/
 
-#define TDB_FORMAT_STRING_V3       "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
+#define SAMU_BUFFER_FORMAT_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
+#define SAMU_BUFFER_FORMAT_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
+#define SAMU_BUFFER_FORMAT_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
+#define SAMU_BUFFER_FORMAT_V3       "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
+/* nothing changed between V3 and V4 */
 
 /*********************************************************************
 *********************************************************************/
 
-bool init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
+static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 
buflen)
+{
+
+       /* times are stored as 32bit integer
+          take care on system with 64bit wide time_t
+          --SSS */
+       uint32  logon_time,
+               logoff_time,
+               kickoff_time,
+               pass_last_set_time,
+               pass_can_change_time,
+               pass_must_change_time;
+       char *username = NULL;
+       char *domain = NULL;
+       char *nt_username = NULL;
+       char *dir_drive = NULL;
+       char *unknown_str = NULL;
+       char *munged_dial = NULL;
+       char *fullname = NULL;
+       char *homedir = NULL;
+       char *logon_script = NULL;
+       char *profile_path = NULL;
+       char *acct_desc = NULL;
+       char *workstations = NULL;
+       uint32  username_len, domain_len, nt_username_len,
+               dir_drive_len, unknown_str_len, munged_dial_len,
+               fullname_len, homedir_len, logon_script_len,
+               profile_path_len, acct_desc_len, workstations_len;
+               
+       uint32  user_rid, group_rid, remove_me, hours_len, unknown_6;
+       uint16  acct_ctrl, logon_divs;
+       uint16  bad_password_count, logon_count;
+       uint8   *hours = NULL;
+       uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
+       uint32          len = 0;
+       uint32          lm_pw_len, nt_pw_len, hourslen;
+       bool ret = True;
+       
+       if(sampass == NULL || buf == NULL) {
+               DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters 
found!\n"));
+               return False;
+       }
+
+/* SAMU_BUFFER_FORMAT_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
+
+       /* unpack the buffer into variables */
+       len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
+               &logon_time,                                            /* d */
+               &logoff_time,                                           /* d */
+               &kickoff_time,                                          /* d */
+               &pass_last_set_time,                                    /* d */
+               &pass_can_change_time,                                  /* d */
+               &pass_must_change_time,                                 /* d */
+               &username_len, &username,                               /* B */
+               &domain_len, &domain,                                   /* B */
+               &nt_username_len, &nt_username,                         /* B */
+               &fullname_len, &fullname,                               /* B */
+               &homedir_len, &homedir,                                 /* B */
+               &dir_drive_len, &dir_drive,                             /* B */
+               &logon_script_len, &logon_script,                       /* B */
+               &profile_path_len, &profile_path,                       /* B */
+               &acct_desc_len, &acct_desc,                             /* B */
+               &workstations_len, &workstations,                       /* B */
+               &unknown_str_len, &unknown_str,                         /* B */
+               &munged_dial_len, &munged_dial,                         /* B */
+               &user_rid,                                              /* d */
+               &group_rid,                                             /* d */
+               &lm_pw_len, &lm_pw_ptr,                                 /* B */
+               &nt_pw_len, &nt_pw_ptr,                                 /* B */
+               &acct_ctrl,                                             /* w */
+               &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
+               &logon_divs,                                            /* w */
+               &hours_len,                                             /* d */
+               &hourslen, &hours,                                      /* B */
+               &bad_password_count,                                    /* w */
+               &logon_count,                                           /* w */
+               &unknown_6);                                            /* d */
+               
+       if (len == (uint32) -1)  {
+               ret = False;
+               goto done;
+       }
+
+       pdb_set_logon_time(sampass, logon_time, PDB_SET);
+       pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
+       pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
+       pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
+       pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
+       pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
+
+       pdb_set_username(sampass, username, PDB_SET); 
+       pdb_set_domain(sampass, domain, PDB_SET);
+       pdb_set_nt_username(sampass, nt_username, PDB_SET);
+       pdb_set_fullname(sampass, fullname, PDB_SET);
+
+       if (homedir) {
+               pdb_set_homedir(sampass, homedir, PDB_SET);
+       }
+       else {
+               pdb_set_homedir(sampass, 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_home()),
+                       PDB_DEFAULT);
+       }
+
+       if (dir_drive)  
+               pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
+       else {
+               pdb_set_dir_drive(sampass, 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_drive()),
+                       PDB_DEFAULT);
+       }
+
+       if (logon_script) 
+               pdb_set_logon_script(sampass, logon_script, PDB_SET);
+       else {
+               pdb_set_logon_script(sampass, 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_script()),
+                       PDB_DEFAULT);
+       }
+       
+       if (profile_path) {     
+               pdb_set_profile_path(sampass, profile_path, PDB_SET);
+       } else {
+               pdb_set_profile_path(sampass, 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_path()),
+                       PDB_DEFAULT);
+       }
+
+       pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
+       pdb_set_workstations(sampass, workstations, PDB_SET);
+       pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+
+       if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
+               if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
+                       ret = False;
+                       goto done;
+               }
+       }
+
+       if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
+               if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
+                       ret = False;
+                       goto done;
+               }
+       }
+
+       pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
+       pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
+       pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
+       pdb_set_hours_len(sampass, hours_len, PDB_SET);
+       pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
+       pdb_set_logon_count(sampass, logon_count, PDB_SET);
+       pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
+       pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
+       pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
+       pdb_set_hours(sampass, hours, PDB_SET);
+
+done:
+
+       SAFE_FREE(username);
+       SAFE_FREE(domain);
+       SAFE_FREE(nt_username);
+       SAFE_FREE(fullname);
+       SAFE_FREE(homedir);
+       SAFE_FREE(dir_drive);
+       SAFE_FREE(logon_script);
+       SAFE_FREE(profile_path);
+       SAFE_FREE(acct_desc);
+       SAFE_FREE(workstations);
+       SAFE_FREE(munged_dial);
+       SAFE_FREE(unknown_str);
+       SAFE_FREE(lm_pw_ptr);
+       SAFE_FREE(nt_pw_ptr);
+       SAFE_FREE(hours);
+
+       return ret;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 
buflen)
+{
+
+       /* times are stored as 32bit integer
+          take care on system with 64bit wide time_t
+          --SSS */
+       uint32  logon_time,
+               logoff_time,
+               kickoff_time,
+               bad_password_time,
+               pass_last_set_time,
+               pass_can_change_time,
+               pass_must_change_time;
+       char *username = NULL;
+       char *domain = NULL;
+       char *nt_username = NULL;
+       char *dir_drive = NULL;
+       char *unknown_str = NULL;
+       char *munged_dial = NULL;
+       char *fullname = NULL;
+       char *homedir = NULL;
+       char *logon_script = NULL;
+       char *profile_path = NULL;
+       char *acct_desc = NULL;
+       char *workstations = NULL;
+       uint32  username_len, domain_len, nt_username_len,
+               dir_drive_len, unknown_str_len, munged_dial_len,
+               fullname_len, homedir_len, logon_script_len,
+               profile_path_len, acct_desc_len, workstations_len;
+               
+       uint32  user_rid, group_rid, remove_me, hours_len, unknown_6;
+       uint16  acct_ctrl, logon_divs;
+       uint16  bad_password_count, logon_count;
+       uint8   *hours = NULL;
+       uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
+       uint32          len = 0;
+       uint32          lm_pw_len, nt_pw_len, hourslen;
+       bool ret = True;
+       
+       if(sampass == NULL || buf == NULL) {
+               DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters 
found!\n"));
+               return False;
+       }
+
+/* SAMU_BUFFER_FORMAT_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
+
+       /* unpack the buffer into variables */
+       len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
+               &logon_time,                                            /* d */
+               &logoff_time,                                           /* d */
+               &kickoff_time,                                          /* d */
+               /* Change from V0 is addition of bad_password_time field. */
+               &bad_password_time,                                     /* d */
+               &pass_last_set_time,                                    /* d */
+               &pass_can_change_time,                                  /* d */
+               &pass_must_change_time,                                 /* d */
+               &username_len, &username,                               /* B */
+               &domain_len, &domain,                                   /* B */
+               &nt_username_len, &nt_username,                         /* B */
+               &fullname_len, &fullname,                               /* B */
+               &homedir_len, &homedir,                                 /* B */
+               &dir_drive_len, &dir_drive,                             /* B */
+               &logon_script_len, &logon_script,                       /* B */
+               &profile_path_len, &profile_path,                       /* B */
+               &acct_desc_len, &acct_desc,                             /* B */
+               &workstations_len, &workstations,                       /* B */
+               &unknown_str_len, &unknown_str,                         /* B */
+               &munged_dial_len, &munged_dial,                         /* B */
+               &user_rid,                                              /* d */
+               &group_rid,                                             /* d */
+               &lm_pw_len, &lm_pw_ptr,                                 /* B */
+               &nt_pw_len, &nt_pw_ptr,                                 /* B */
+               &acct_ctrl,                                             /* w */
+               &remove_me,                                             /* d */
+               &logon_divs,                                            /* w */
+               &hours_len,                                             /* d */
+               &hourslen, &hours,                                      /* B */
+               &bad_password_count,                                    /* w */
+               &logon_count,                                           /* w */
+               &unknown_6);                                            /* d */
+               
+       if (len == (uint32) -1)  {
+               ret = False;
+               goto done;
+       }
+
+       pdb_set_logon_time(sampass, logon_time, PDB_SET);
+       pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
+       pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
+
+       /* Change from V0 is addition of bad_password_time field. */
+       pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
+       pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
+       pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
+       pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
+
+       pdb_set_username(sampass, username, PDB_SET); 
+       pdb_set_domain(sampass, domain, PDB_SET);
+       pdb_set_nt_username(sampass, nt_username, PDB_SET);
+       pdb_set_fullname(sampass, fullname, PDB_SET);
+
+       if (homedir) {
+               pdb_set_homedir(sampass, homedir, PDB_SET);
+       }
+       else {
+               pdb_set_homedir(sampass, 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_home()),
+                       PDB_DEFAULT);
+       }
+
+       if (dir_drive)  
+               pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
+       else {
+               pdb_set_dir_drive(sampass, 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_drive()),
+                       PDB_DEFAULT);
+       }
+
+       if (logon_script) 
+               pdb_set_logon_script(sampass, logon_script, PDB_SET);
+       else {
+               pdb_set_logon_script(sampass, 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_script()),
+                       PDB_DEFAULT);
+       }
+       
+       if (profile_path) {     
+               pdb_set_profile_path(sampass, profile_path, PDB_SET);
+       } else {
+               pdb_set_profile_path(sampass, 
+                       talloc_sub_basic(sampass, username, domain,
+                                        lp_logon_path()),
+                       PDB_DEFAULT);
+       }
+
+       pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
+       pdb_set_workstations(sampass, workstations, PDB_SET);
+       pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+
+       if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
+               if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
+                       ret = False;
+                       goto done;
+               }
+       }
+
+       if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
+               if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
+                       ret = False;
+                       goto done;
+               }
+       }
+
+       pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
+
+       pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
+       pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
+       pdb_set_hours_len(sampass, hours_len, PDB_SET);
+       pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
+       pdb_set_logon_count(sampass, logon_count, PDB_SET);
+       pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
+       pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
+       pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
+       pdb_set_hours(sampass, hours, PDB_SET);
+
+done:
+
+       SAFE_FREE(username);
+       SAFE_FREE(domain);
+       SAFE_FREE(nt_username);
+       SAFE_FREE(fullname);


-- 
Samba Shared Repository

Reply via email to