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