1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2003-2021 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include "pop3d.h"
18
19 #ifdef ENABLE_LOGIN_DELAY
20
21 static mu_dbm_file_t
open_stat_db(int mode)22 open_stat_db (int mode)
23 {
24 mu_dbm_file_t db;
25 int rc;
26
27 rc = mu_dbm_create (login_stat_file, &db, DEFAULT_GROUP_DB_SAFETY);
28 if (rc)
29 {
30 mu_diag_output (MU_DIAG_ERROR, _("unable to create statistics db"));
31 return NULL;
32 }
33
34 rc = mu_dbm_safety_check (db);
35 if (rc && rc != ENOENT)
36 {
37 mu_diag_output (MU_DIAG_ERROR,
38 _("statistics db fails safety check: %s"),
39 mu_strerror (rc));
40 mu_dbm_destroy (&db);
41 return NULL;
42 }
43
44 rc = mu_dbm_open (db, mode, 0660);
45 if (rc)
46 {
47 mu_diag_output (MU_DIAG_ERROR, _("unable to open statistics db: %s"),
48 mu_dbm_strerror (db));
49 mu_dbm_destroy (&db);
50 }
51 return db;
52 }
53
54 int
check_login_delay(char * username)55 check_login_delay (char *username)
56 {
57 time_t now, prev_time;
58 mu_dbm_file_t db;
59 struct mu_dbm_datum key, data;
60 char text[64], *p;
61 int rc;
62
63 if (login_delay == 0)
64 return 0;
65
66 time (&now);
67 db = open_stat_db (MU_STREAM_READ);
68 if (!db)
69 return 0;
70
71 memset (&key, 0, sizeof key);
72 key.mu_dptr = username;
73 key.mu_dsize = strlen (username);
74 memset (&data, 0, sizeof data);
75
76 rc = mu_dbm_fetch (db, &key, &data);
77 if (rc)
78 {
79 if (rc != MU_ERR_NOENT)
80 mu_diag_output (MU_DIAG_ERROR, _("cannot fetch login delay data: %s"),
81 mu_dbm_strerror (db));
82 mu_dbm_destroy (&db);
83 return 0;
84 }
85
86 if (data.mu_dsize > sizeof (text) - 1)
87 {
88 mu_diag_output (MU_DIAG_ERROR,
89 _("invalid entry for '%s': wrong timestamp size"),
90 username);
91 mu_dbm_destroy (&db);
92 return 0;
93 }
94 mu_dbm_destroy (&db);
95
96 memcpy (text, data.mu_dptr, data.mu_dsize);
97 text[data.mu_dsize] = 0;
98 mu_dbm_datum_free (&data);
99
100 prev_time = strtoul (text, &p, 0);
101 if (*p)
102 {
103 mu_diag_output (MU_DIAG_ERROR,
104 _("malformed timestamp for '%s': %s"),
105 username, text);
106 return 0;
107 }
108
109 return now - prev_time < login_delay;
110 }
111
112 void
update_login_delay(char * username)113 update_login_delay (char *username)
114 {
115 time_t now;
116 mu_dbm_file_t db;
117 struct mu_dbm_datum key, data;
118 char text[64];
119
120 if (login_delay == 0 || username == NULL)
121 return;
122
123 time (&now);
124 db = open_stat_db (MU_STREAM_RDWR);
125 if (!db)
126 return;
127
128 memset(&key, 0, sizeof(key));
129 memset(&data, 0, sizeof(data));
130 key.mu_dptr = username;
131 key.mu_dsize = strlen (username);
132 snprintf (text, sizeof text, "%lu", (unsigned long) now);
133 data.mu_dptr = text;
134 data.mu_dsize = strlen (text);
135 if (mu_dbm_store (db, &key, &data, 1))
136 mu_error (_("%s: cannot store datum %s/%s: %s"),
137 login_stat_file, username, text,
138 mu_dbm_strerror (db));
139
140 mu_dbm_destroy (&db);
141 }
142
143 void
login_delay_capa(const char * name,struct pop3d_session * session)144 login_delay_capa (const char *name, struct pop3d_session *session)
145 {
146 mu_dbm_file_t db;
147
148 if (login_delay && (db = open_stat_db (MU_STREAM_RDWR)) != NULL)
149 {
150 pop3d_outf ("%lu\n", (unsigned long) login_delay);
151 mu_dbm_destroy (&db);
152 }
153 }
154 #endif
155