1 /*
2 **  NetNews Reading Protocol server.
3 */
4 
5 #include "config.h"
6 #include "portable/macros.h"
7 #include "portable/socket.h"
8 
9 #include <ctype.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <sys/stat.h>
13 #include <syslog.h>
14 
15 #ifdef HAVE_SYS_TIME_H
16 #    include <sys/time.h>
17 #endif
18 #include <time.h>
19 
20 #include "inn/libinn.h"
21 #include "inn/nntp.h"
22 #include "inn/paths.h"
23 #include "inn/qio.h"
24 #include "inn/storage.h"
25 #include "inn/timer.h"
26 #include "inn/vector.h"
27 
28 #ifdef HAVE_SASL
29 #    include <sasl/sasl.h>
30 #    include <sasl/saslutil.h>
31 #endif
32 
33 #if defined(HAVE_ZLIB)
34 #    include <zlib.h>
35 #endif
36 
37 /*
38 **  A range of article numbers.
39 */
40 typedef struct _ARTRANGE {
41     ARTNUM Low;
42     ARTNUM High;
43 } ARTRANGE;
44 
45 /*
46 **  Access configuration for each reader.
47 */
48 typedef struct _ACCESSGROUP {
49     char *name;
50     char *key;
51     char *read;
52     char *post;
53     char *users;
54     char *rejectwith;
55     int allownewnews;
56     bool allowihave;
57     int locpost;
58     int allowapproved;
59     int used;
60     int localtime;
61     int strippath;
62     int nnrpdperlfilter;
63     int nnrpdpythonfilter;
64     char *fromhost;
65     char *pathhost;
66     char *organization;
67     char *moderatormailer;
68     char *domain;
69     char *complaints;
70     int spoolfirst;
71     int checkincludedtext;
72     int clienttimeout;
73     unsigned long localmaxartsize;
74     int readertrack;
75     int strippostcc;
76     int addinjectiondate;
77     int addinjectionpostingaccount;
78     int addinjectionpostinghost;
79     char *nnrpdposthost;
80     unsigned long nnrpdpostport;
81     int nnrpdoverstats;
82     int backoff_auth;
83     char *backoff_db;
84     unsigned long backoff_k;
85     unsigned long backoff_postfast;
86     unsigned long backoff_postslow;
87     unsigned long backoff_trigger;
88     int nnrpdcheckart;
89     int nnrpdauthsender;
90     int virtualhost;
91     char *newsmaster;
92     long maxbytespersecond;
93 } ACCESSGROUP;
94 
95 /*
96 **  What line_read returns.
97 */
98 typedef enum _READTYPE
99 {
100     RTeof,
101     RTok,
102     RTlong,
103     RTtimeout
104 } READTYPE;
105 
106 
107 /*
108 **  Structure used by line_read to keep track of what has been read.
109 */
110 struct line {
111     char *start;
112     char *where;
113     size_t remaining;
114     size_t allocated;
115 };
116 
117 
118 /*
119 **  Information about the currently connected client.  Eventually, this struct
120 **  may become the repository for all nnrpd global state, or at least the
121 **  state that relates to a particular client connection.
122 */
123 struct client {
124     char host[SMBUF];
125     char ip[INET6_ADDRSTRLEN];
126     unsigned short port;
127     char serverhost[SMBUF];
128     char serverip[INET6_ADDRSTRLEN];
129     unsigned short serverport;
130 };
131 
132 
133 /*
134 **  Information about the schema of the news overview files.
135 */
136 typedef struct _ARTOVERFIELD {
137     char *Header;
138     int Length;
139     bool NeedsHeader;
140 } ARTOVERFIELD;
141 
142 /*
143 **  Supported timers.  If you add new timers to this list, also add them to
144 **  the list of tags in nnrpd.c.
145 */
146 enum timer
147 {
148     TMR_IDLE = TMR_APPLICATION, /* Server is completely idle. */
149     TMR_NEWNEWS,                /* Executing NEWNEWS command. */
150     TMR_READART,                /* Reading an article (SMretrieve). */
151     TMR_CHECKART,               /* Checking an article (ARTinstorebytoken). */
152     TMR_NNTPREAD,               /* Reading from the peer. */
153     TMR_NNTPWRITE,              /* Writing to the peer. */
154     TMR_MAX
155 };
156 
157 /*
158 **  Do not change "extern" to "EXTERN" below.  The ones marked with "extern"
159 **  are initialized in nnrpd.c.  The ones marked with "EXTERN" are not
160 **  explicitly initialized in nnrpd.c.
161 */
162 #if defined(MAINLINE)
163 #    define EXTERN /* NULL */
164 #else
165 #    define EXTERN extern
166 #endif /* defined(MAINLINE) */
167 
168 EXTERN bool PERMauthorized;
169 EXTERN bool PERMcanauthenticate;
170 #if defined(HAVE_OPENSSL) || defined(HAVE_SASL)
171 EXTERN bool PERMcanauthenticatewithoutSSL;
172 #endif
173 EXTERN bool PERMcanpost;
174 EXTERN bool PERMcanpostgreeting;
175 EXTERN bool PERMcanread;
176 EXTERN bool PERMneedauth;
177 EXTERN bool PERMspecified;
178 EXTERN bool PERMgroupmadeinvalid;
179 EXTERN ACCESSGROUP *PERMaccessconf;
180 EXTERN bool Tracing;
181 EXTERN bool Offlinepost;
182 EXTERN bool initialSSL;
183 EXTERN char **PERMreadlist;
184 EXTERN char **PERMpostlist;
185 EXTERN struct client Client;
186 EXTERN char Username[SMBUF];
187 extern char *ACTIVETIMES;
188 extern char *HISTORY;
189 extern char *ACTIVE;
190 extern char *NEWSGROUPS;
191 extern char *NNRPACCESS;
192 EXTERN char PERMuser[SMBUF];
193 EXTERN FILE *locallog;
194 EXTERN ARTNUM ARTnumber;       /* Current article number. */
195 EXTERN ARTNUM ARThigh;         /* Current high number for group. */
196 EXTERN ARTNUM ARTlow;          /* Current low number for group. */
197 EXTERN unsigned long ARTcount; /* Number of articles in group. */
198 EXTERN long MaxBytesPerSecond; /* Maximum bytes per sec a client can use,
199                                   defaults to 0. */
200 EXTERN long ARTget;
201 EXTERN long ARTgettime;
202 EXTERN long ARTgetsize;
203 EXTERN long OVERcount;    /* Number of (X)OVER commands. */
204 EXTERN long OVERhit;      /* Number of (X)OVER records found in overview. */
205 EXTERN long OVERmiss;     /* Number of (X)OVER records found in articles. */
206 EXTERN long OVERtime;     /* Number of ms spent sending (X)OVER data. */
207 EXTERN long OVERsize;     /* Number of bytes of (X)OVER data sent. */
208 EXTERN long OVERdbz;      /* Number of ms spent reading dbz data. */
209 EXTERN long OVERseek;     /* Number of ms spent seeking history. */
210 EXTERN long OVERget;      /* Number of ms spent reading history. */
211 EXTERN long OVERartcheck; /* Number of ms spent article check. */
212 EXTERN double IDLEtime;
213 EXTERN unsigned long GRParticles;
214 EXTERN long GRPcount;
215 EXTERN char *GRPcur;
216 EXTERN long POSTreceived;
217 EXTERN long POSTrejected;
218 
219 EXTERN bool BACKOFFenabled;
220 EXTERN char *VirtualPath;
221 EXTERN int VirtualPathlen;
222 EXTERN struct history *History;
223 EXTERN struct line NNTPline;
224 EXTERN struct vector *OVextra;
225 EXTERN int overhdr_xref;
226 EXTERN bool LLOGenable;
227 
228 extern const char *NNRPinstance;
229 extern bool laxmid;
230 #if defined(HAVE_OPENSSL) || defined(HAVE_SASL)
231 extern bool encryption_layer_on;
232 #endif
233 
234 #if defined(DO_PERL)
235 extern bool PerlLoaded;
236 #endif
237 
238 extern const char *ARTpost(char *article, char *idbuff, bool *permanent);
239 extern void ARTclose(void);
240 extern int TrimSpaces(char *line);
241 extern void InitBackoffConstants(void);
242 extern char *PostRecFilename(char *ip, char *user);
243 extern int LockPostRec(char *path);
244 extern void UnlockPostRec(char *path);
245 extern int RateLimit(long *sleeptime, char *path);
246 extern void ExitWithStats(int x, bool readconf) __attribute__((__noreturn__));
247 extern char *GetHeader(const char *header, bool stripspaces);
248 extern void GRPreport(void);
249 extern bool NGgetlist(char ***argvp, char *list);
250 extern bool PERMartok(void);
251 extern void PERMgetinitialaccess(char *readersconf);
252 extern void PERMgetaccess(bool initialconnection);
253 extern void PERMgetpermissions(void);
254 extern void PERMlogin(char *uname, char *pass, int *code, char *errorstr);
255 extern bool PERMmatch(char **Pats, char **list);
256 extern bool ParseDistlist(char ***argvp, char *list);
257 extern void SetDefaultAccess(ACCESSGROUP *);
258 extern void Reply(const char *fmt, ...)
259     __attribute__((__format__(printf, 1, 2)));
260 extern void Printf(const char *fmt, ...)
261     __attribute__((__format__(printf, 1, 2)));
262 
263 extern void CMDauthinfo(int ac, char **av);
264 extern void CMDcapabilities(int ac, char **av);
265 #if defined(HAVE_ZLIB)
266 extern void CMDcompress(int ac, char **av);
267 #endif
268 extern void CMDdate(int ac, char **av);
269 extern void CMDfetch(int ac, char **av);
270 extern void CMDgroup(int ac, char **av);
271 extern void CMDhelp(int ac, char **av);
272 extern void CMDlist(int ac, char **av);
273 extern void CMDmode(int ac, char **av);
274 extern void CMDnewgroups(int ac, char **av);
275 extern void CMDnewnews(int ac, char **av);
276 extern void CMDnextlast(int ac, char **av);
277 extern void CMDover(int ac, char **av);
278 extern void CMDpost(int ac, char **av);
279 extern void CMDquit(int ac, char **av) __attribute__((__noreturn__));
280 extern void CMDxgtitle(int ac, char **av);
281 extern void CMDpat(int ac, char **av);
282 extern void CMD_unimp(int ac, char **av);
283 #ifdef HAVE_OPENSSL
284 extern void CMDstarttls(int ac, char **av);
285 #endif
286 
287 extern bool CMDgetrange(int ac, char *av[], ARTRANGE *rp, bool *DidReply);
288 
289 /*
290 **  Run a resolver or authenticator.  The directory is where to look for the
291 **  command if not fully qualified.  username and password may be NULL to run
292 **  resolvers.
293 */
294 char *auth_external(struct client *, const char *command,
295                     const char *directory, const char *username,
296                     const char *password);
297 
298 void write_buffer(const char *buff, ssize_t len);
299 
300 extern char *HandleHeaders(char *article);
301 extern bool ARTinstorebytoken(TOKEN token);
302 
303 extern int TrackClient(char *client, char *user, size_t len);
304 
305 #ifdef DO_PERL
306 extern void loadPerl(void);
307 extern void perlAccess(char *user, struct vector *access_vec);
308 extern void perlAuthenticate(char *user, char *passwd, int *code,
309                              char *errorstring, char *newUser);
310 extern void perlAuthInit(void);
311 #endif /* DO_PERL */
312 
313 #ifdef DO_PYTHON
314 extern bool PY_use_dynamic;
315 
316 void PY_authenticate(char *path, char *Username, char *Password, int *code,
317                      char *errorstring, char *newUser);
318 void PY_access(char *path, struct vector *access_vec, char *Username);
319 void PY_close_python(void);
320 int PY_dynamic(char *Username, char *NewsGroup, int PostFlag,
321                char **reply_message);
322 void PY_dynamic_init(char *file);
323 #    if PY_MAJOR_VERSION >= 3
324 extern PyMODINIT_FUNC PyInit_nnrpd(void);
325 #    else
326 extern void PyInit_nnrpd(void);
327 #    endif
328 #endif /* DO_PYTHON */
329 
330 void line_free(struct line *);
331 void line_init(struct line *);
332 void line_reset(struct line *);
333 READTYPE line_read(struct line *, int, const char **, size_t *, size_t *);
334 
335 #ifdef HAVE_SASL
336 extern sasl_conn_t *sasl_conn;
337 extern int sasl_ssf, sasl_maxout;
338 extern sasl_callback_t sasl_callbacks[];
339 
340 void SASLauth(int ac, char *av[]);
341 void SASLnewserver(void);
342 #endif /* HAVE_SASL */
343 
344 #if defined(HAVE_SASL) || defined(HAVE_ZLIB)
345 bool IsValidAlgorithm(const char *);
346 #endif /* HAVE_SASL || HAVE_ZLIB */
347 
348 #if defined(HAVE_ZLIB)
349 extern bool compression_layer_on;
350 extern bool tls_compression_on;
351 /* (De)compress streams and related variables. */
352 extern z_stream *zstream_in;
353 extern z_stream *zstream_out;
354 extern bool zstream_inflate_needed;
355 extern bool zstream_flush_needed;
356 /* (De)compress buffers and related variables. */
357 extern unsigned char *zbuf_in;
358 extern size_t zbuf_in_allocated;
359 extern size_t zbuf_in_size;
360 extern unsigned char *zbuf_out;
361 extern size_t zbuf_out_size;
362 
363 bool zlib_init(void);
364 #endif /* HAVE_ZLIB */
365