~james-page/ubuntu/raring/dovecot/autopkgtest

« back to all changes in this revision

Viewing changes to src/director/user-directory.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 11:11:54 UTC
  • mfrom: (1.15.2) (4.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120611111154-678cwbdj6ktgsv1h
Tags: 1:2.1.7-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/{control,rules}: enable PIE hardening.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + d/control: Added Pre-Depends: dpkg (>= 1.15.6) to dovecot-dbg to support
    xz compression in Ubuntu.
  + d/control: Demote dovecot-common Recommends: to Suggests: to prevent
    install of extra packages on upgrade.
  + d/patches/dovecot-drac.patch: Updated with version for dovecot >= 2.0.0.
  + d/control: Drop B-D on systemd.
* Dropped changes:
  + d/patches/fix-racey-restart.patch: part of 2.1.x, no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "ioloop.h"
5
5
#include "array.h"
6
 
#include "md5.h"
7
6
#include "hash.h"
8
7
#include "llist.h"
 
8
#include "mail-user-hash.h"
9
9
#include "mail-host.h"
10
10
#include "user-directory.h"
11
11
 
12
 
#define MAX_CLOCK_DRIFT_SECS 2
 
12
/* n% of timeout_secs */
 
13
#define USER_NEAR_EXPIRING_PERCENTAGE 10
 
14
/* but max. of this many secs */
 
15
#define USER_NEAR_EXPIRING_MAX 30
13
16
 
14
17
struct user_directory_iter {
15
18
        struct user_directory *dir;
21
24
        struct hash_table *hash;
22
25
        /* sorted by time */
23
26
        struct user *head, *tail;
 
27
        struct user *prev_insert_pos;
24
28
 
25
29
        ARRAY_DEFINE(iters, struct user_directory_iter *);
26
30
 
 
31
        char *username_hash_fmt;
27
32
        unsigned int timeout_secs;
 
33
        /* If user's expire time is less than this many seconds away,
 
34
           don't assume that other directors haven't yet expired it */
 
35
        unsigned int user_near_expiring_secs;
28
36
};
29
37
 
30
38
static void user_move_iters(struct user_directory *dir, struct user *user)
35
43
                if ((*iterp)->pos == user)
36
44
                        (*iterp)->pos = user->next;
37
45
        }
 
46
 
 
47
        if (dir->prev_insert_pos == user)
 
48
                dir->prev_insert_pos = user->next;
38
49
}
39
50
 
40
51
static void user_free(struct user_directory *dir, struct user *user)
49
60
        i_free(user);
50
61
}
51
62
 
 
63
static bool user_directory_user_has_connections(struct user_directory *dir,
 
64
                                                struct user *user)
 
65
{
 
66
        time_t expire_timestamp = user->timestamp + dir->timeout_secs;
 
67
 
 
68
        return expire_timestamp >= ioloop_time;
 
69
}
 
70
 
52
71
static void user_directory_drop_expired(struct user_directory *dir)
53
72
{
54
73
        while (dir->head != NULL &&
64
83
        return hash_table_lookup(dir->hash, POINTER_CAST(username_hash));
65
84
}
66
85
 
 
86
static void
 
87
user_directory_insert_backwards(struct user_directory *dir,
 
88
                                struct user *pos, struct user *user)
 
89
{
 
90
        for (; pos != NULL; pos = pos->prev) {
 
91
                if ((time_t)pos->timestamp <= user->timestamp)
 
92
                        break;
 
93
        }
 
94
        if (pos == NULL)
 
95
                DLLIST2_PREPEND(&dir->head, &dir->tail, user);
 
96
        else {
 
97
                user->prev = pos;
 
98
                user->next = pos->next;
 
99
                user->prev->next = user;
 
100
                if (user->next != NULL)
 
101
                        user->next->prev = user;
 
102
                else
 
103
                        dir->tail = user;
 
104
        }
 
105
}
 
106
 
 
107
static void
 
108
user_directory_insert_forwards(struct user_directory *dir,
 
109
                               struct user *pos, struct user *user)
 
110
{
 
111
        for (; pos != NULL; pos = pos->next) {
 
112
                if ((time_t)pos->timestamp >= user->timestamp)
 
113
                        break;
 
114
        }
 
115
        if (pos == NULL)
 
116
                DLLIST2_APPEND(&dir->head, &dir->tail, user);
 
117
        else {
 
118
                user->prev = pos->prev;
 
119
                user->next = pos;
 
120
                if (user->prev != NULL)
 
121
                        user->prev->next = user;
 
122
                else
 
123
                        dir->head = user;
 
124
                user->next->prev = user;
 
125
        }
 
126
}
 
127
 
67
128
struct user *
68
129
user_directory_add(struct user_directory *dir, unsigned int username_hash,
69
130
                   struct mail_host *host, time_t timestamp)
70
131
{
71
 
        struct user *user, *pos;
 
132
        struct user *user;
 
133
 
 
134
        /* make sure we don't add timestamps higher than ioloop time */
 
135
        if (timestamp > ioloop_time)
 
136
                timestamp = ioloop_time;
72
137
 
73
138
        user = i_new(struct user, 1);
74
139
        user->username_hash = username_hash;
79
144
        if (dir->tail == NULL || (time_t)dir->tail->timestamp <= timestamp)
80
145
                DLLIST2_APPEND(&dir->head, &dir->tail, user);
81
146
        else {
82
 
                /* need to insert to correct position */
83
 
                for (pos = dir->tail; pos != NULL; pos = pos->prev) {
84
 
                        if ((time_t)pos->timestamp <= timestamp)
85
 
                                break;
86
 
                }
87
 
                if (pos == NULL)
88
 
                        DLLIST2_PREPEND(&dir->head, &dir->tail, user);
89
 
                else {
90
 
                        user->prev = pos;
91
 
                        user->next = pos->next;
92
 
                        user->prev->next = user;
93
 
                        user->next->prev = user;
 
147
                /* need to insert to correct position. we should get here
 
148
                   only when handshaking. the handshaking USER requests should
 
149
                   come sorted by timestamp. so keep track of the previous
 
150
                   insert position, the next USER should be inserted after
 
151
                   it. */
 
152
                if (dir->prev_insert_pos == NULL) {
 
153
                        /* find the position starting from tail */
 
154
                        user_directory_insert_backwards(dir, dir->tail, user);
 
155
                } else if (timestamp < dir->prev_insert_pos->timestamp) {
 
156
                        user_directory_insert_backwards(dir, dir->prev_insert_pos,
 
157
                                                        user);
 
158
                } else {
 
159
                        user_directory_insert_forwards(dir, dir->prev_insert_pos,
 
160
                                                       user);
94
161
                }
95
162
        }
96
163
 
 
164
        dir->prev_insert_pos = user;
97
165
        hash_table_insert(dir->hash, POINTER_CAST(user->username_hash), user);
98
166
        return user;
99
167
}
120
188
        }
121
189
}
122
190
 
123
 
unsigned int user_directory_get_username_hash(const char *username)
124
 
{
125
 
        /* NOTE: If you modify this, modify also
126
 
           director_username_hash() in login-common/login-proxy.c */
127
 
        unsigned char md5[MD5_RESULTLEN];
128
 
        unsigned int i, hash = 0;
129
 
 
130
 
        md5_get_digest(username, strlen(username), md5);
131
 
        for (i = 0; i < sizeof(hash); i++)
132
 
                hash = (hash << CHAR_BIT) | md5[i];
133
 
        return hash;
134
 
}
135
 
 
136
 
bool user_directory_user_has_connections(struct user_directory *dir,
137
 
                                         struct user *user)
138
 
{
139
 
        time_t expire_timestamp = user->timestamp + dir->timeout_secs;
140
 
 
141
 
        return expire_timestamp - MAX_CLOCK_DRIFT_SECS >= ioloop_time;
142
 
}
143
 
 
144
 
struct user_directory *user_directory_init(unsigned int timeout_secs)
 
191
unsigned int user_directory_get_username_hash(struct user_directory *dir,
 
192
                                              const char *username)
 
193
{
 
194
        return mail_user_hash(username, dir->username_hash_fmt);
 
195
}
 
196
 
 
197
bool user_directory_user_is_recently_updated(struct user_directory *dir,
 
198
                                             struct user *user)
 
199
{
 
200
        return (time_t)(user->timestamp + dir->timeout_secs/2) >= ioloop_time;
 
201
}
 
202
 
 
203
bool user_directory_user_is_near_expiring(struct user_directory *dir,
 
204
                                          struct user *user)
 
205
{
 
206
        time_t expire_timestamp;
 
207
 
 
208
        expire_timestamp = user->timestamp +
 
209
                (dir->timeout_secs - dir->user_near_expiring_secs);
 
210
        return expire_timestamp < ioloop_time;
 
211
}
 
212
 
 
213
struct user_directory *
 
214
user_directory_init(unsigned int timeout_secs, const char *username_hash_fmt)
145
215
{
146
216
        struct user_directory *dir;
147
217
 
148
218
        dir = i_new(struct user_directory, 1);
149
219
        dir->timeout_secs = timeout_secs;
 
220
        dir->user_near_expiring_secs =
 
221
                timeout_secs * USER_NEAR_EXPIRING_PERCENTAGE / 100;
 
222
        dir->user_near_expiring_secs =
 
223
                I_MIN(dir->user_near_expiring_secs, USER_NEAR_EXPIRING_MAX);
 
224
        dir->user_near_expiring_secs =
 
225
                I_MAX(dir->user_near_expiring_secs, 1);
 
226
 
 
227
        dir->username_hash_fmt = i_strdup(username_hash_fmt);
150
228
        dir->hash = hash_table_create(default_pool, default_pool,
151
229
                                      0, NULL, NULL);
152
230
        i_array_init(&dir->iters, 8);
165
243
                user_free(dir, dir->head);
166
244
        hash_table_destroy(&dir->hash);
167
245
        array_free(&dir->iters);
 
246
        i_free(dir->username_hash_fmt);
168
247
        i_free(dir);
169
248
}
170
249
 
177
256
        iter->dir = dir;
178
257
        iter->pos = dir->head;
179
258
        array_append(&dir->iters, &iter, 1);
 
259
        user_directory_drop_expired(dir);
180
260
        return iter;
181
261
}
182
262