aboutsummaryrefslogtreecommitdiff
path: root/src/wydawca.h
blob: b390bffc0e83bcd1f15ebaa7bf613f362fd005f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
/* wydawca - automatic release submission daemon
   Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 3 of the License, or (at your
   option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program. If not, see <http://www.gnu.org/licenses/>. */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <syslog.h>
#include <getopt.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <pwd.h>
#include <grp.h>
#include <signal.h>
#include <limits.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <time.h>
#include <sysexits.h>

#include <mailutils/types.h>
#include <mailutils/url.h>
#include <mailutils/errno.h>

#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
#include "obstack.h"
#include "error.h"
#include "xalloc.h"
#include "progname.h"
#include "backupfile.h"
#include "inttostr.h"
#include "grecs.h"
#include "gl_list.h"
#include "wordsplit.h"

#define gettext(s) s
#define _(s) s
#define N_(s) s

#define SP(s) ((s) ? (s) : "NONE")

#define WYDAWCA_EX_AGAIN 1

/* The range of directive versions we accept (major * 100 + minor) */
#define MIN_DIRECTIVE_VERSION 101
#define MAX_DIRECTIVE_VERSION 101

/* Default modes for mkdir and creat commands: rely on the umask value */
#define MKDIR_PERMISSIONS 0777
#define CREAT_PERMISSIONS 0666

#define SUF_SIG ".sig"
#define SUF_SIG_LEN (sizeof (SUF_SIG) - 1)
#define SUF_DIR ".directive.asc"
#define SUF_DIR_LEN (sizeof (SUF_DIR) - 1)

#define __cat2__(a,b) a ## b
#define __cat3__(a,b,c) a ## b ## c
#define NITEMS(a) (sizeof(a)/sizeof((a)[0]))

enum access_method_id {
  verify_method,        /* Method for verification user's access to
			   the project */
  gpg_key_method,       /* Method for retrieving the user public key */
  project_owner_method, /* Method for retrieving the names
			   and emails of the project owners */
  user_data_method,     /* Method for retrieving the user name
			   and real name by his uid */
  access_method_count
};

enum access_method_type
  {
    method_none,           /* Undefined or no method */
    method_sql,            /* Use SQL database */
    method_builtin,        /* Use built-in facilities */
    method_external        /* Invoke an external program */
  };

struct access_method
{
  enum access_method_id id;
  enum access_method_type type;   /* Access method type */
  char *query;                    /* Query template */
  int parmc;                      /* Number of entries in paramv */
  char **parmv;                   /* Parameters. The semantics differs
				     depending on type. For SQL:
				      0 - Identifier of the SQL struct
				          to use; */

  int init_passed;                /* Initialization count */
  char *result;                   /* Result storage */
  size_t result_size;             /* Size of result */
  unsigned ncol;                  /* Number of columns per row */
  unsigned nrow;                  /* Number of rows */

  void *storage;
};


/* Archive types */

enum archive_type
  {
    archive_none,         /* No archivation requested */
    archive_directory,    /* Archive by moving files to a separate directory
			     hierarchy */
    archive_tar           /* Archive by appending to a tar file (tar -r) */
  };

struct archive_descr
{
  enum archive_type type;        /* Archivation type */
  char *name;                    /* Directory name if type==archive_directory,
				    archive file name if type==archive_tar */
  enum backup_type backup_type;  /* Requested backup type if
				    type == archive_directory */
};


/* Type of file in a triplet */
enum file_type
  {
    file_dist,             /* Something to be distributed */
    file_signature,        /* Detached signature (.sig) */
    file_directive,        /* Directive (.directive.asc) */
  };
#define FILE_TYPE_COUNT (file_directive+1)

/* Part of a triplet */
struct file_info
{
  enum file_type type;     /* Part type */
  char *name;              /* File name */
  unsigned root_len;       /* Length of root part in name */
  struct stat sb;
};

/* File triplet */
struct file_triplet
{
  char *name;              /* Triplet base name */
  gid_t gid;               /* Owner GID */
  struct file_info file[FILE_TYPE_COUNT]; /* Components */
  const struct spool *spool;     /* Owning spool */
  char **directive;        /* Decoded directive pairs (key: value\0) */
  char *blurb;             /* Block of directives: directive[i] points here */
  char *tmp;               /* Temporary storage */
  size_t tmpsize;          /* Size of memory allocated in tmp */
  /* Special data for template formatting */
  char *project;           /* Triplet project name (if known) */
  char *user;              /* User name (if known) */
  char **user_data;
};

/* Macros to access owner UID and GID. */
/* The directive file is always present in the triplet */
#define TRIPLET_UID(t) ((t)->file[file_directive].sb.st_uid)
/* GID is filled in after the triplet is finalized and verified */
#define TRIPLET_GID(t) ((t)->gid)



struct virt_tab
{
  int (*test_url)      (mu_url_t url, grecs_locus_t *loc);
  int (*move_file)     (struct file_triplet *trp,
			const struct spool *spool,
			enum file_type file_id,
			const char *reldir);
  int (*archive_file)  (struct file_triplet *trp,
			const struct spool *spool,
			const char *reldir,
			const char *file_name);
  int (*symlink_file)  (struct file_triplet *trp,
			const struct spool *spool,
			const char *reldir,
			const char *wanted_src,
			const char *wanted_dst);
  int (*rmsymlink_file)(struct file_triplet *trp,
			const struct spool *spool,
			const char *reldir,
			const char *file_name);
};

/* An upload spool. This structure contains all data necessary for releasing 
   files from source to destination */
struct spool
{
  char *tag;
  gl_list_t aliases;
  char *url;                             /* Download URL */
  char *source_dir;                      /* Source directory */
  mu_url_t dest_url;                     /* Destination URL */
  const char *dest_dir;                  /* Directory part of the above */
  struct virt_tab vtab;                  /* Virtual method table */
  
  time_t file_sweep_time;                /* Remove invalid/unprocessed files
					    after this amount of time */
  struct access_method *access_method[access_method_count];
  struct archive_descr archive;          /* Archivation data */
  struct notification *notification;
};


enum wydawca_stat
  {
    STAT_ERRORS,
    STAT_WARNINGS,
    STAT_BAD_SIGNATURE,
    STAT_ACCESS_VIOLATIONS,
    STAT_COMPLETE_TRIPLETS,
    STAT_INCOMPLETE_TRIPLETS,
    STAT_BAD_TRIPLETS,
    STAT_EXPIRED_TRIPLETS,
    STAT_TRIPLET_SUCCESS,
    STAT_UPLOADS,
    STAT_ARCHIVES,
    STAT_SYMLINKS,
    STAT_RMSYMLINKS,
    MAX_STAT
  };

#define STAT_MASK(c) (1<<(c))
#define STAT_MASK_NONE 0
#define STAT_MASK_ALL  (STAT_MASK(MAX_STAT) - 1)


enum notification_event
  {
    ev_success,
    ev_bad_ownership,
    ev_bad_directive_signature,
    ev_bad_detached_signature,
    MAX_EVENT
  };

enum notification_target
  {
    notify_admin,        /* System administrator */
    notify_owner,        /* Project admin */
    notify_user          /* User (uploader) */
  };

struct notification
{
  struct notification *next;
  enum notification_event ev;
  enum notification_target tgt;
  const char *msg;
};

void register_message_template (const char *name, const char *text);

void notify (struct notification *,
	     struct file_triplet *, enum notification_event);

const char *notification_event_str (enum notification_event evt);
const char *notification_target_str (enum notification_target tgt);


struct metadef
{
  char *kw;
  char *value;
  const char *(*expand) (struct metadef *, void *);
  char *storage;
  void *data;
};

char *meta_expand_string (const char *string, struct metadef *def, void *data,
			  struct access_method *method, void *handle);
void meta_free (struct metadef *def);


/* Global variables */
extern uid_t wydawca_uid;
extern gid_t wydawca_gid;
extern size_t wydawca_supp_groupc;
extern gid_t *wydawca_supp_groups;
extern char *conffile;         /* Configuration file name */
extern int debug_level;        /* Debugging level */
extern int dry_run_mode;       /* Dry run indicator */
extern int log_to_stderr;      /* Log to stderr instead of the syslog */
extern int log_facility;       /* Syslog facility to use if !log_to_stderr */
extern char *syslog_tag;       /* Syslog tag */
extern int syslog_include_prio;/* Syslog priority indication */
extern time_t file_sweep_time; /* Unlink stale file after this amount of time
				*/
extern char *tar_command_name; /* Name of the tar command */
extern unsigned wydawca_stat[MAX_STAT];
extern unsigned long print_stats;
extern int archive_signatures;

extern char *admin_stat_message;

extern char *pidfile;
extern int force_startup;

extern char *lockdir;
extern time_t lock_expire_time;
unsigned lock_retry_attempts;
time_t lock_retry_interval;
extern int enable_locking;

extern int daemon_mode;
extern time_t wakeup_interval;
extern int foreground;
extern int single_process;
extern struct grecs_sockaddr listen_sockaddr;

extern gl_list_t all_spool_aliases;

#define UPDATE_STATS(what)			\
  do						\
    {						\
      if (what >= MAX_STAT) abort();		\
      wydawca_stat[what]++;			\
    }						\
  while (0)

int stat_mask_p (unsigned long mask);
struct metadef *make_stat_expansion (size_t count);
void initstats (void);
void logstats (void);


/* Utility functions */
char *safe_file_name (char *file_name);
char *safe_file_name_alloc (const char *file_name);
size_t trim_length (const char *str);
size_t trim (char *str);
void logmsg (int prio, char *fmt, ...) GSC_PRINTFLIKE(2,3);
int test_dir (const char *name, int *ec);
char *create_directory (const char *base, const char *name);
int create_hierarchy (char *dir, size_t baselen);
void parse_config (void);
void log_output (int prio, const char *prog, FILE *fp);

enum exec_result
  {
    exec_success,    /* Command executed and returned 0 */
    exec_fail,       /* Command executed and returned not 0 */
    exec_error       /* Command failed to execute */
  };

enum exec_result wydawca_exec (int argc, const char **argv, int *retcode);


/* Directory scanning and registering */
int scan_spool (const struct spool *spool, int uc, uid_t *uv);
int scan_all_spools (int, uid_t *);
void spool_create_timers (void);

void register_spool (struct spool *spool);
struct spool *wydawca_find_spool (const char *name);
void register_file (struct file_info *finfo);
void enumerate_triplets (const struct spool *);
size_t count_collected_triplets (void);
char *triplet_expand_param (const char *tmpl, struct file_triplet *trp);
char *triplet_expand_method_query (struct access_method *method, void *handle,
				   struct file_triplet *trp);

/* General-purpose method support */
struct access_method *method_new (enum access_method_id id,
				  enum access_method_type type);
int method_init (struct access_method *method);
int method_done (struct access_method *method);
void *method_open (struct access_method *method);
int method_close (struct access_method *method, void *handle);
int method_run (struct access_method *method, void *handle, const char *cmd);
void method_copy_result (struct access_method *method, const char *res,
			 size_t size);
const char *method_result (struct access_method *method, void *handle,
			   unsigned nrow,
			   unsigned ncol);
int method_quote_string (struct access_method *method, void *handle,
			 const char *input, char **poutput, size_t *psize);

unsigned method_num_rows (struct access_method *method);
unsigned method_num_cols (struct access_method *method);

/* Verification functions */
int verify_directive_file (struct file_triplet *trp,
			   const struct spool *spool);
int verify_directive_signature (struct file_triplet *trp,
				const struct spool *spool,
				const char *pubkey);
int verify_detached_signature (struct file_triplet *trp,
			       const struct spool *spool);
int fill_project_name (struct file_triplet *trp);

/* Directive file support */
int directive_parse (struct file_triplet *trp);
int directive_get_value (struct file_triplet *trp, const char *key,
			 const char **pval);
int directive_pack_version (const char *val, unsigned *pversion);
int directive_version_in_range_p (struct file_triplet *trp,
				  unsigned from, unsigned to);
int verify_directive_format (struct file_triplet *trp);
int directive_first (struct file_triplet *trp,
		     const char **pkey, const char **pval);
int directive_next (struct file_triplet *trp, int n,
		    const char **pkey, const char **pval);
int process_directives (struct file_triplet *trp,
			const struct spool *spool);

int enabled_spool_p (const struct spool *spool);



int parse_time_interval (const char *str, time_t *pint, const char **endp);


/* config.c */
void config_init (void);
void config_help (void);
int assert_string_arg (grecs_locus_t *, enum grecs_callback_command,
		       const grecs_value_t *);


/* vtab.c */
int url_to_vtab (mu_url_t url, struct virt_tab *vtab);

int
move_file (struct file_triplet *trp, const struct spool *spool,
	   enum file_type file_id, const char *reldir);	  
int
archive_file (struct file_triplet *trp, const struct spool *spool,
	      const char *reldir, const char *file_name);	  
int
symlink_file (struct file_triplet *trp, const struct spool *spool,
	      const char *reldir,
	      const char *wanted_src, const char *wanted_dst);
int
rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
		const char *reldir, const char *file_name);


/* diskio.c */

int dir_test_url (mu_url_t url, grecs_locus_t *locus);
int dir_move_file (struct file_triplet *trp, const struct spool *spool,
		   enum file_type file_id, const char *reldir);
int dir_archive_file (struct file_triplet *trp, const struct spool *spool,
		      const char *file_name, const char *reldir);
int dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
		      const char *reldir,
		      const char *wanted_src, const char *wanted_dst);
int dir_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
			const char *reldir, const char *file_name);

/* null.c */
int null_move_file (struct file_triplet *trp, const struct spool *spool,
		    enum file_type file_id, const char *reldir);
int null_archive_file (struct file_triplet *trp, const struct spool *spool,
		       const char *file_name, const char *reldir);
int null_symlink_file (struct file_triplet *trp, const struct spool *spool,
		       const char *reldir,
		       const char *wanted_src, const char *wanted_dst);
int null_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
			 const char *reldir, const char *file_name);


/* timer.c */
typedef struct timer_slot *wydawca_timer_t;

wydawca_timer_t timer_get (const char *name);
wydawca_timer_t timer_start (const char *name);
wydawca_timer_t timer_stop (const char *name);
wydawca_timer_t timer_reset (const char *name);
double timer_get_real (wydawca_timer_t t);
double timer_get_user (wydawca_timer_t t);
double timer_get_system (wydawca_timer_t t);
char *timer_format_time (double t);
size_t timer_get_count (void);
void timer_fill_meta (struct metadef *def, size_t num);
void timer_free_meta (struct metadef *def, size_t num);


void report_init (void);
void report_add (const char *fmt, ...);
void report_finish (void);
extern char *report_string;


/* job.c */
void schedule_job (const struct spool *spool, uid_t uid);
void job_init (void);
void job_queue_runner (void);


/* profile.c */
void check_pidfile (void);
void remove_pidfile (void);


/* net.c */
void wydawca_listener (void);


#define LOCK_OK          0
#define LOCK_CONFLICT    1
#define LOCK_RETRY       2
#define LOCK_INVALID     3
#define LOCK_FAILURE     4

char *wydawca_lockname (const char *tag);
int wydawca_lock (const char *lockname);
void wydawca_unlock (const char *lockname);
void wydawca_lock_init (void);


/* tcpwrap.h */
extern struct grecs_keyword tcpwrapper_kw[];
int tcpwrap_access(int fd);

/* userprivs.c */
int wydawca_userprivs (uid_t uid, gid_t gid, gid_t *grplist, size_t ngrp);

Return to:

Send suggestions and report system problems to the System administrator.