Mercurial > dovecot > core-2.2
comparison src/director/director-connection.c @ 22691:dca05b22217b
director: Fix crash when handling expired USER timestamps.
The fix in 154f91726624265fce15097eb4bbbf6e55f8c477 wasn't complete.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Tue, 28 Nov 2017 13:10:35 +0200 |
parents | ac58eecfb8b0 |
children | 281472b3bb20 |
comparison
equal
deleted
inserted
replaced
22690:b66965f62ae8 | 22691:dca05b22217b |
---|---|
590 return FALSE; | 590 return FALSE; |
591 } | 591 } |
592 return TRUE; | 592 return TRUE; |
593 } | 593 } |
594 | 594 |
595 static bool | 595 static int |
596 director_user_refresh(struct director_connection *conn, | 596 director_user_refresh(struct director_connection *conn, |
597 unsigned int username_hash, struct mail_host *host, | 597 unsigned int username_hash, struct mail_host *host, |
598 time_t timestamp, bool weak, bool *forced_r, | 598 time_t timestamp, bool weak, bool *forced_r, |
599 struct user **user_r) | 599 struct user **user_r) |
600 { | 600 { |
610 /* Old director version sent USER without timestamp. */ | 610 /* Old director version sent USER without timestamp. */ |
611 timestamp = ioloop_time; | 611 timestamp = ioloop_time; |
612 } | 612 } |
613 | 613 |
614 if (timestamp + (time_t)dir->set->director_user_expire <= ioloop_time) { | 614 if (timestamp + (time_t)dir->set->director_user_expire <= ioloop_time) { |
615 /* Ignore this refresh entirely, regardless of whether the | |
616 user already exists or not. */ | |
615 dir_debug("user refresh: %u has expired timestamp %ld", | 617 dir_debug("user refresh: %u has expired timestamp %ld", |
616 username_hash, (long)timestamp); | 618 username_hash, (long)timestamp); |
617 return TRUE; | 619 return -1; |
618 } | 620 } |
619 | 621 |
620 user = user_directory_lookup(users, username_hash); | 622 user = user_directory_lookup(users, username_hash); |
621 if (user == NULL) { | 623 if (user == NULL) { |
622 *user_r = user_directory_add(users, username_hash, | 624 *user_r = user_directory_add(users, username_hash, |
623 host, timestamp); | 625 host, timestamp); |
624 (*user_r)->weak = weak; | 626 (*user_r)->weak = weak; |
625 dir_debug("user refresh: %u added", username_hash); | 627 dir_debug("user refresh: %u added", username_hash); |
626 return TRUE; | 628 return 1; |
627 } | 629 } |
628 | 630 |
629 if (user->weak) { | 631 if (user->weak) { |
630 if (!weak) { | 632 if (!weak) { |
631 /* removing user's weakness */ | 633 /* removing user's weakness */ |
742 this user if there are any */ | 744 this user if there are any */ |
743 director_set_state_changed(conn->dir); | 745 director_set_state_changed(conn->dir); |
744 } | 746 } |
745 | 747 |
746 *user_r = user; | 748 *user_r = user; |
747 return ret; | 749 return ret ? 1 : 0; |
748 } | 750 } |
749 | 751 |
750 static bool | 752 static bool |
751 director_handshake_cmd_user(struct director_connection *conn, | 753 director_handshake_cmd_user(struct director_connection *conn, |
752 const char *const *args) | 754 const char *const *args) |
779 compared to us. Don't set any of our users' timestamps into | 781 compared to us. Don't set any of our users' timestamps into |
780 future though. It's most likely only 1 second difference. */ | 782 future though. It's most likely only 1 second difference. */ |
781 timestamp = ioloop_time; | 783 timestamp = ioloop_time; |
782 } | 784 } |
783 conn->dir->num_incoming_requests++; | 785 conn->dir->num_incoming_requests++; |
784 (void)director_user_refresh(conn, username_hash, host, | 786 if (director_user_refresh(conn, username_hash, host, |
785 timestamp, weak, &forced, &user); | 787 timestamp, weak, &forced, &user) < 0) { |
788 /* user expired - ignore */ | |
789 return TRUE; | |
790 } | |
786 /* Possibilities: | 791 /* Possibilities: |
787 | 792 |
788 a) The user didn't exist yet, and it was added with the given | 793 a) The user didn't exist yet, and it was added with the given |
789 timestamp. | 794 timestamp. |
790 | 795 |
834 /* we probably just removed this host. */ | 839 /* we probably just removed this host. */ |
835 return TRUE; | 840 return TRUE; |
836 } | 841 } |
837 | 842 |
838 if (director_user_refresh(conn, username_hash, | 843 if (director_user_refresh(conn, username_hash, |
839 host, timestamp, FALSE, &forced, &user)) { | 844 host, timestamp, FALSE, &forced, &user) > 0) { |
845 /* user changed - forward the USER in the ring */ | |
840 struct director_host *src_host = | 846 struct director_host *src_host = |
841 forced ? conn->dir->self_host : conn->host; | 847 forced ? conn->dir->self_host : conn->host; |
842 i_assert(!user->weak); | 848 i_assert(!user->weak); |
843 director_update_user(conn->dir, src_host, user); | 849 director_update_user(conn->dir, src_host, user); |
844 } | 850 } |
1057 dir_debug("user refresh: %u Remote USER-WEAK from %s seen by the entire ring, ignoring", | 1063 dir_debug("user refresh: %u Remote USER-WEAK from %s seen by the entire ring, ignoring", |
1058 username_hash, dir_host->ip_str); | 1064 username_hash, dir_host->ip_str); |
1059 weak_forward = TRUE; | 1065 weak_forward = TRUE; |
1060 } | 1066 } |
1061 | 1067 |
1062 if (director_user_refresh(conn, username_hash, | 1068 ret = director_user_refresh(conn, username_hash, |
1063 host, ioloop_time, weak, &forced, &user) || | 1069 host, ioloop_time, weak, &forced, &user); |
1064 weak_forward) { | 1070 /* user is refreshed with ioloop_time, it can't be expired already */ |
1071 i_assert(ret >= 0); | |
1072 if (ret > 0 || weak_forward) { | |
1073 /* user changed, or we've decided that we need to forward | |
1074 the weakness notification to the rest of the ring even | |
1075 though we already knew it. */ | |
1065 if (forced) | 1076 if (forced) |
1066 src_host = conn->dir->self_host; | 1077 src_host = conn->dir->self_host; |
1067 if (!user->weak) | 1078 if (!user->weak) |
1068 director_update_user(conn->dir, src_host, user); | 1079 director_update_user(conn->dir, src_host, user); |
1069 else { | 1080 else { |