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