Enhance audit logs to support SysV message queues
[openafs.git] / src / kauth / kaserver.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13
14 #include <afs/stds.h>
15 #include <sys/types.h>
16 #ifdef AFS_NT40_ENV
17 #include <winsock2.h>
18 #include <WINNT/afsevent.h>
19 #else
20 #include <sys/file.h>
21 #include <netdb.h>
22 #include <netinet/in.h>
23 #endif
24 #include "kalog.h"              /* for OpenLog() */
25 #include <time.h>
26 #include <stdio.h>
27 #include <string.h>
28 #ifdef HAVE_FCNTL_H
29 #include <fcntl.h>
30 #endif
31 #ifdef  AFS_AIX32_ENV
32 #include <signal.h>
33 #endif
34 #include <lwp.h>
35 #include <rx/xdr.h>
36 #include <rx/rx.h>
37 #include <rx/rxkad.h>
38 #include <rx/rx_globals.h>
39 #include <afs/cellconfig.h>
40 #include <lock.h>
41 #include <afs/afsutil.h>
42 #include <afs/com_err.h>
43 #include <afs/audit.h>
44 #include <ubik.h>
45 #include <sys/stat.h>
46 #include "kauth.h"
47 #include "kautils.h"
48 #include "kaserver.h"
49 #include "kadatabase.h"
50 #include "kaprocs.h"
51
52 struct kadstats dynamic_statistics;
53 struct ubik_dbase *KA_dbase;
54 afs_int32 myHost = 0;
55 afs_int32 verbose_track = 1;
56 afs_int32 krb4_cross = 0;
57 afs_int32 rxBind = 0;
58
59 #define ADDRSPERSITE 16         /* Same global is in rx/rx_user.c */
60 afs_uint32 SHostAddrs[ADDRSPERSITE];
61
62 struct afsconf_dir *KA_conf;    /* for getting cell info */
63
64 int MinHours = 0;
65 int npwSums = KA_NPWSUMS;       /* needs to be variable sometime */
66
67 #include <stdarg.h>
68 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
69 #undef vfprintf
70 #define vfprintf(stream,fmt,args) _doprnt(fmt,args,stream)
71 #endif
72
73 static int debugOutput;
74
75 /* check whether caller is authorized to manage RX statistics */
76 int
77 KA_rxstat_userok(struct rx_call *call)
78 {
79     return afsconf_SuperUser(KA_conf, call, NULL);
80 }
81
82 afs_int32
83 es_Report(char *fmt, ...)
84 {
85     va_list pvar;
86
87     if (debugOutput == 0)
88         return 0;
89     va_start(pvar, fmt);
90     vfprintf(stderr, fmt, pvar);
91     va_end(pvar);
92     return 0;
93 }
94
95 static void
96 initialize_dstats(void)
97 {
98     memset(&dynamic_statistics, 0, sizeof(dynamic_statistics));
99     dynamic_statistics.start_time = time(0);
100     dynamic_statistics.host = myHost;
101 }
102
103 static int
104 convert_cell_to_ubik(struct afsconf_cell *cellinfo, afs_int32 *myHost,
105                      afs_int32 *serverList)
106 {
107     int i;
108     char hostname[64];
109     struct hostent *th;
110
111     /* get this host */
112     gethostname(hostname, sizeof(hostname));
113     th = gethostbyname(hostname);
114     if (!th) {
115         ViceLog(0, ("kaserver: couldn't get address of this host.\n"));
116         exit(1);
117     }
118     memcpy(myHost, th->h_addr, sizeof(afs_int32));
119
120     for (i = 0; i < cellinfo->numServers; i++)
121         if (cellinfo->hostAddr[i].sin_addr.s_addr != *myHost) {
122             /* omit my host from serverList */
123             *serverList++ = cellinfo->hostAddr[i].sin_addr.s_addr;
124         }
125     *serverList = 0;            /* terminate list */
126     return 0;
127 }
128
129 static afs_int32
130 kvno_admin_key(void *rock, afs_int32 kvno, struct ktc_encryptionKey *key)
131 {
132     return ka_LookupKvno(0, KA_ADMIN_NAME, KA_ADMIN_INST, kvno, key);
133
134     /* we would like to start a Ubik transaction to fill the cache if that
135      * fails, but may deadlock as Rx is now organized. */
136 }
137
138 /* initFlags: 0x01  Do not require authenticated connections.
139               0x02  Do not check the bos NoAuth flag
140               0x04  Use fast key expiration to test oldkey code.
141               0x08  Temporary flag allowing database inconsistency fixup
142  */
143
144 #include "AFS_component_version_number.c"
145
146 int
147 main(int argc, char *argv[])
148 {
149     afs_int32 code;
150     char *whoami = argv[0];
151     afs_int32 serverList[MAXSERVERS];
152     struct afsconf_cell cellinfo;
153     char *cell;
154     const char *cellservdb, *dbpath, *lclpath;
155     int a;
156     char arg[32];
157     char default_lclpath[AFSDIR_PATH_MAX];
158     int servers;
159     int initFlags;
160     int level;                  /* security level for Ubik */
161     afs_int32 i;
162     char clones[MAXHOSTSPERCELL];
163     afs_uint32 host = ntohl(INADDR_ANY);
164     char *auditFileName = NULL;
165
166     struct rx_service *tservice;
167     struct rx_securityClass *sca[1];
168     struct rx_securityClass *scm[3];
169
170     extern int rx_stackSize;
171     extern int KAA_ExecuteRequest(struct rx_call *);
172     extern int KAT_ExecuteRequest(struct rx_call *);
173     extern int KAM_ExecuteRequest(struct rx_call *);
174     extern int RXSTATS_ExecuteRequest(struct rx_call *);
175
176 #ifdef  AFS_AIX32_ENV
177     /*
178      * The following signal action for AIX is necessary so that in case of a 
179      * crash (i.e. core is generated) we can include the user's data section 
180      * in the core dump. Unfortunately, by default, only a partial core is
181      * generated which, in many cases, isn't too useful.
182      */
183     struct sigaction nsa;
184
185     sigemptyset(&nsa.sa_mask);
186     nsa.sa_handler = SIG_DFL;
187     nsa.sa_flags = SA_FULLDUMP;
188     sigaction(SIGABRT, &nsa, NULL);
189     sigaction(SIGSEGV, &nsa, NULL);
190 #endif
191     osi_audit_init();
192
193     if (argc == 0) {
194       usage:
195         printf("Usage: kaserver [-noAuth] [-fastKeys] [-database <dbpath>] "
196                "[-auditlog <log path>] [-audit-interface <file|sysvmq>] "
197                "[-rxbind] [-localfiles <lclpath>] [-minhours <n>] "
198                "[-servers <serverlist>] [-crossrealm] "
199                /*" [-enable_peer_stats] [-enable_process_stats] " */
200                "[-help]\n");
201         exit(1);
202     }
203 #ifdef AFS_NT40_ENV
204     /* initialize winsock */
205     if (afs_winsockInit() < 0) {
206         ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);
207         fprintf(stderr, "%s: Couldn't initialize winsock.\n", whoami);
208         exit(1);
209     }
210 #endif
211     /* Initialize dirpaths */
212     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
213 #ifdef AFS_NT40_ENV
214         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
215 #endif
216         fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
217                 argv[0]);
218         exit(2);
219     }
220
221     cellservdb = AFSDIR_SERVER_ETC_DIRPATH;
222     dbpath = AFSDIR_SERVER_KADB_FILEPATH;
223     strcompose(default_lclpath, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH,
224                "/", AFSDIR_KADB_FILE, NULL);
225     lclpath = default_lclpath;
226
227     debugOutput = 0;
228     servers = 0;
229     initFlags = 0;
230     level = rxkad_crypt;
231     for (a = 1; a < argc; a++) {
232         int arglen = strlen(argv[a]);
233         lcstring(arg, argv[a], sizeof(arg));
234 #define IsArg(a) (strncmp (arg,a, arglen) == 0)
235
236         if (strcmp(arg, "-database") == 0) {
237             dbpath = argv[++a];
238             if (strcmp(lclpath, default_lclpath) == 0)
239                 lclpath = dbpath;
240         }
241         else if (strncmp(arg, "-auditlog", arglen) == 0) {
242             auditFileName = argv[++a];
243
244         } else if (strncmp(arg, "-audit-interface", arglen) == 0) {
245             char *interface = argv[++a];
246
247             if (osi_audit_interface(interface)) {
248                 printf("Invalid audit interface '%s'\n", interface);
249                 exit(1);
250             }
251             
252         } else if (strcmp(arg, "-localfiles") == 0)
253             lclpath = argv[++a];
254         else if (strcmp(arg, "-servers") == 0)
255             debugOutput++, servers = 1;
256         else if (strcmp(arg, "-noauth") == 0)
257             debugOutput++, initFlags |= 1;
258         else if (strcmp(arg, "-fastkeys") == 0)
259             debugOutput++, initFlags |= 4;
260         else if (strcmp(arg, "-dbfixup") == 0)
261             debugOutput++, initFlags |= 8;
262         else if (strcmp(arg, "-cellservdb") == 0) {
263             cellservdb = argv[++a];
264             initFlags |= 2;
265             debugOutput++;
266         }
267
268         else if (IsArg("-crypt"))
269             level = rxkad_crypt;
270         else if (IsArg("-safe"))
271             level = rxkad_crypt;
272         else if (IsArg("-clear"))
273             level = rxkad_clear;
274         else if (IsArg("-sorry"))
275             level = rxkad_clear;
276         else if (IsArg("-debug"))
277             verbose_track = 0;
278         else if (IsArg("-crossrealm"))
279             krb4_cross = 1;
280         else if (IsArg("-rxbind"))
281             rxBind = 1;
282         else if (IsArg("-minhours")) {
283             MinHours = atoi(argv[++a]);
284         } else if (IsArg("-enable_peer_stats")) {
285             rx_enablePeerRPCStats();
286         } else if (IsArg("-enable_process_stats")) {
287             rx_enableProcessRPCStats();
288         } else if (*arg == '-') {
289             /* hack to support help flag */
290             goto usage;
291         }
292     }
293
294     if (auditFileName) {
295         osi_audit_file(auditFileName);
296     }
297
298     if ((code = ka_CellConfig(cellservdb)))
299         goto abort;
300     cell = ka_LocalCell();
301     KA_conf = afsconf_Open(cellservdb);
302     if (!KA_conf) {
303         code = KANOCELLS;
304       abort:
305         afs_com_err(whoami, code, "Failed getting cell info");
306         exit(1);
307     }
308 #ifdef        AUTH_DBM_LOG
309     kalog_Init();
310 #else
311     /* NT & HPUX do not have dbm package support. So we can only do some
312      * text logging. So open the AuthLog file for logging and redirect
313      * stdin and stdout to it 
314      */
315     OpenLog(AFSDIR_SERVER_KALOG_FILEPATH);
316     SetupLogSignals();
317 #endif
318
319     fprintf(stderr, "%s: WARNING: kaserver is deprecated due to its weak security "
320             "properties.  Migrating to a Kerberos 5 KDC is advised.  "
321             "http://www.openafs.org/no-more-des.html\n", whoami);
322     ViceLog(0, ("WARNING: kaserver is deprecated due to its weak security properties.  "
323             "Migrating to a Kerberos 5 KDC is advised.  "
324             "http://www.openafs.org/no-more-des.html\n"));
325
326     code =
327         afsconf_GetExtendedCellInfo(KA_conf, cell, AFSCONF_KAUTHSERVICE,
328                                     &cellinfo, &clones);
329     if (servers) {
330         if ((code = ubik_ParseServerList(argc, argv, &myHost, serverList))) {
331             afs_com_err(whoami, code, "Couldn't parse server list");
332             exit(1);
333         }
334         cellinfo.hostAddr[0].sin_addr.s_addr = myHost;
335         for (i = 1; i < MAXSERVERS; i++) {
336             if (!serverList[i])
337                 break;
338             cellinfo.hostAddr[i].sin_addr.s_addr = serverList[i];
339         }
340         cellinfo.numServers = i;
341     } else {
342         code = convert_cell_to_ubik(&cellinfo, &myHost, serverList);
343         if (code)
344             goto abort;
345         ViceLog(0, ("Using server list from %s cell database.\n", cell));
346     }
347
348     /* initialize ubik */
349     if (level == rxkad_clear)
350         ubik_CRXSecurityProc = afsconf_ClientAuth;
351     else if (level == rxkad_crypt)
352         ubik_CRXSecurityProc = afsconf_ClientAuthSecure;
353     else {
354         ViceLog(0, ("Unsupported security level %d\n", level));
355         exit(5);
356     }
357     ViceLog(0,
358             ("Using level %s for Ubik connections.\n",
359              (level == rxkad_crypt ? "crypt" : "clear")));
360     ubik_CRXSecurityRock = (char *)KA_conf;
361     ubik_SRXSecurityProc = afsconf_ServerAuth;
362     ubik_SRXSecurityRock = (char *)KA_conf;
363     ubik_CheckRXSecurityProc = afsconf_CheckAuth;
364     ubik_CheckRXSecurityRock = (char *)KA_conf;
365
366     ubik_nBuffers = 80;
367
368     if (rxBind) {
369         afs_int32 ccode;
370         if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || 
371             AFSDIR_SERVER_NETINFO_FILEPATH) {
372             char reason[1024];
373             ccode = parseNetFiles(SHostAddrs, NULL, NULL,
374                                            ADDRSPERSITE, reason,
375                                            AFSDIR_SERVER_NETINFO_FILEPATH,
376                                            AFSDIR_SERVER_NETRESTRICT_FILEPATH);
377         } else 
378         {
379             ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
380         }
381         if (ccode == 1) {
382             host = SHostAddrs[0];
383             rx_InitHost(host, htons(AFSCONF_KAUTHPORT));
384         }
385     }
386
387     if (servers)
388         code =
389             ubik_ServerInit(myHost, htons(AFSCONF_KAUTHPORT), serverList,
390                             dbpath, &KA_dbase);
391     else
392         code =
393             ubik_ServerInitByInfo(myHost, htons(AFSCONF_KAUTHPORT), &cellinfo,
394                                   clones, dbpath, &KA_dbase);
395
396     if (code) {
397         afs_com_err(whoami, code, "Ubik init failed");
398         exit(2);
399     }
400
401     sca[RX_SCINDEX_NULL] = rxnull_NewServerSecurityObject();
402
403     /* Disable jumbograms */
404     rx_SetNoJumbo();
405
406     tservice =
407         rx_NewServiceHost(host, 0, KA_AUTHENTICATION_SERVICE, 
408                           "AuthenticationService", sca, 1, KAA_ExecuteRequest);
409     if (tservice == (struct rx_service *)0) {
410         ViceLog(0, ("Could not create Authentication rx service\n"));
411         exit(3);
412     }
413     rx_SetMinProcs(tservice, 1);
414     rx_SetMaxProcs(tservice, 1);
415
416     
417     tservice =
418         rx_NewServiceHost(host, 0, KA_TICKET_GRANTING_SERVICE, "TicketGrantingService",
419                       sca, 1, KAT_ExecuteRequest);
420     if (tservice == (struct rx_service *)0) {
421         ViceLog(0, ("Could not create Ticket Granting rx service\n"));
422         exit(3);
423     }
424     rx_SetMinProcs(tservice, 1);
425     rx_SetMaxProcs(tservice, 1);
426
427     scm[RX_SCINDEX_NULL] = sca[RX_SCINDEX_NULL];
428     scm[RX_SCINDEX_VAB] = 0;
429     scm[RX_SCINDEX_KAD] =
430         rxkad_NewServerSecurityObject(rxkad_crypt, 0, kvno_admin_key, 0);
431     tservice =
432         rx_NewServiceHost(host, 0, KA_MAINTENANCE_SERVICE, "Maintenance", scm, 3,
433                       KAM_ExecuteRequest);
434     if (tservice == (struct rx_service *)0) {
435         ViceLog(0, ("Could not create Maintenance rx service\n"));
436         exit(3);
437     }
438     rx_SetMinProcs(tservice, 1);
439     rx_SetMaxProcs(tservice, 1);
440     rx_SetStackSize(tservice, 10000);
441
442     tservice =
443         rx_NewServiceHost(host, 0, RX_STATS_SERVICE_ID, "rpcstats", scm, 3,
444                       RXSTATS_ExecuteRequest);
445     if (tservice == (struct rx_service *)0) {
446         ViceLog(0, ("Could not create rpc stats rx service\n"));
447         exit(3);
448     }
449     rx_SetMinProcs(tservice, 2);
450     rx_SetMaxProcs(tservice, 4);
451
452     initialize_dstats();
453
454     /* allow super users to manage RX statistics */
455     rx_SetRxStatUserOk(KA_rxstat_userok);
456
457     rx_StartServer(0);          /* start handling req. of all types */
458
459     if (init_kaprocs(lclpath, initFlags))
460         return -1;
461
462     if ((code = init_krb_udp())) {
463         ViceLog(0,
464                 ("Failed to initialize UDP interface; code = %d.\n", code));
465         ViceLog(0, ("Running without UDP access.\n"));
466     }
467
468     ViceLog(0, ("Starting to process AuthServer requests\n"));
469     rx_ServerProc(NULL);                /* donate this LWP */
470     return 0;
471 }