Parallel make: additional fixes
[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
165     struct rx_service *tservice;
166     struct rx_securityClass *sca[1];
167     struct rx_securityClass *scm[3];
168
169     extern int rx_stackSize;
170     extern int KAA_ExecuteRequest(struct rx_call *);
171     extern int KAT_ExecuteRequest(struct rx_call *);
172     extern int KAM_ExecuteRequest(struct rx_call *);
173     extern int RXSTATS_ExecuteRequest(struct rx_call *);
174
175 #ifdef  AFS_AIX32_ENV
176     /*
177      * The following signal action for AIX is necessary so that in case of a 
178      * crash (i.e. core is generated) we can include the user's data section 
179      * in the core dump. Unfortunately, by default, only a partial core is
180      * generated which, in many cases, isn't too useful.
181      */
182     struct sigaction nsa;
183
184     sigemptyset(&nsa.sa_mask);
185     nsa.sa_handler = SIG_DFL;
186     nsa.sa_flags = SA_FULLDUMP;
187     sigaction(SIGABRT, &nsa, NULL);
188     sigaction(SIGSEGV, &nsa, NULL);
189 #endif
190     osi_audit_init();
191
192     if (argc == 0) {
193       usage:
194         printf("Usage: kaserver [-noAuth] [-fastKeys] [-database <dbpath>] "
195                "[-auditlog <log path>] [-rxbind] "
196                "[-localfiles <lclpath>] [-minhours <n>] [-servers <serverlist>] "
197                "[-crossrealm]"
198                /*" [-enable_peer_stats] [-enable_process_stats] " */
199                "[-help]\n");
200         exit(1);
201     }
202 #ifdef AFS_NT40_ENV
203     /* initialize winsock */
204     if (afs_winsockInit() < 0) {
205         ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);
206         fprintf(stderr, "%s: Couldn't initialize winsock.\n", whoami);
207         exit(1);
208     }
209 #endif
210     /* Initialize dirpaths */
211     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
212 #ifdef AFS_NT40_ENV
213         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
214 #endif
215         fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
216                 argv[0]);
217         exit(2);
218     }
219
220     cellservdb = AFSDIR_SERVER_ETC_DIRPATH;
221     dbpath = AFSDIR_SERVER_KADB_FILEPATH;
222     strcompose(default_lclpath, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH,
223                "/", AFSDIR_KADB_FILE, NULL);
224     lclpath = default_lclpath;
225
226     debugOutput = 0;
227     servers = 0;
228     initFlags = 0;
229     level = rxkad_crypt;
230     for (a = 1; a < argc; a++) {
231         int arglen = strlen(argv[a]);
232         lcstring(arg, argv[a], sizeof(arg));
233 #define IsArg(a) (strncmp (arg,a, arglen) == 0)
234
235         if (strcmp(arg, "-database") == 0) {
236             dbpath = argv[++a];
237             if (strcmp(lclpath, default_lclpath) == 0)
238                 lclpath = dbpath;
239         }
240         else if (strncmp(arg, "-auditlog", arglen) == 0) {
241             char *fileName = argv[++a];
242             
243             osi_audit_file(fileName);
244         } else if (strcmp(arg, "-localfiles") == 0)
245             lclpath = argv[++a];
246         else if (strcmp(arg, "-servers") == 0)
247             debugOutput++, servers = 1;
248         else if (strcmp(arg, "-noauth") == 0)
249             debugOutput++, initFlags |= 1;
250         else if (strcmp(arg, "-fastkeys") == 0)
251             debugOutput++, initFlags |= 4;
252         else if (strcmp(arg, "-dbfixup") == 0)
253             debugOutput++, initFlags |= 8;
254         else if (strcmp(arg, "-cellservdb") == 0) {
255             cellservdb = argv[++a];
256             initFlags |= 2;
257             debugOutput++;
258         }
259
260         else if (IsArg("-crypt"))
261             level = rxkad_crypt;
262         else if (IsArg("-safe"))
263             level = rxkad_crypt;
264         else if (IsArg("-clear"))
265             level = rxkad_clear;
266         else if (IsArg("-sorry"))
267             level = rxkad_clear;
268         else if (IsArg("-debug"))
269             verbose_track = 0;
270         else if (IsArg("-crossrealm"))
271             krb4_cross = 1;
272         else if (IsArg("-rxbind"))
273             rxBind = 1;
274         else if (IsArg("-minhours")) {
275             MinHours = atoi(argv[++a]);
276         } else if (IsArg("-enable_peer_stats")) {
277             rx_enablePeerRPCStats();
278         } else if (IsArg("-enable_process_stats")) {
279             rx_enableProcessRPCStats();
280         } else if (*arg == '-') {
281             /* hack to support help flag */
282             goto usage;
283         }
284     }
285     if ((code = ka_CellConfig(cellservdb)))
286         goto abort;
287     cell = ka_LocalCell();
288     KA_conf = afsconf_Open(cellservdb);
289     if (!KA_conf) {
290         code = KANOCELLS;
291       abort:
292         afs_com_err(whoami, code, "Failed getting cell info");
293         exit(1);
294     }
295 #ifdef        AUTH_DBM_LOG
296     kalog_Init();
297 #else
298     /* NT & HPUX do not have dbm package support. So we can only do some
299      * text logging. So open the AuthLog file for logging and redirect
300      * stdin and stdout to it 
301      */
302     OpenLog(AFSDIR_SERVER_KALOG_FILEPATH);
303     SetupLogSignals();
304 #endif
305
306     fprintf(stderr, "%s: WARNING: kaserver is deprecated due to its weak security "
307             "properties.  Migrating to a Kerberos 5 KDC is advised.  "
308             "http://www.openafs.org/no-more-des.html\n", whoami);
309     ViceLog(0, ("WARNING: kaserver is deprecated due to its weak security properties.  "
310             "Migrating to a Kerberos 5 KDC is advised.  "
311             "http://www.openafs.org/no-more-des.html\n"));
312
313     code =
314         afsconf_GetExtendedCellInfo(KA_conf, cell, AFSCONF_KAUTHSERVICE,
315                                     &cellinfo, &clones);
316     if (servers) {
317         if ((code = ubik_ParseServerList(argc, argv, &myHost, serverList))) {
318             afs_com_err(whoami, code, "Couldn't parse server list");
319             exit(1);
320         }
321         cellinfo.hostAddr[0].sin_addr.s_addr = myHost;
322         for (i = 1; i < MAXSERVERS; i++) {
323             if (!serverList[i])
324                 break;
325             cellinfo.hostAddr[i].sin_addr.s_addr = serverList[i];
326         }
327         cellinfo.numServers = i;
328     } else {
329         code = convert_cell_to_ubik(&cellinfo, &myHost, serverList);
330         if (code)
331             goto abort;
332         ViceLog(0, ("Using server list from %s cell database.\n", cell));
333     }
334
335     /* initialize ubik */
336     if (level == rxkad_clear)
337         ubik_CRXSecurityProc = afsconf_ClientAuth;
338     else if (level == rxkad_crypt)
339         ubik_CRXSecurityProc = afsconf_ClientAuthSecure;
340     else {
341         ViceLog(0, ("Unsupported security level %d\n", level));
342         exit(5);
343     }
344     ViceLog(0,
345             ("Using level %s for Ubik connections.\n",
346              (level == rxkad_crypt ? "crypt" : "clear")));
347     ubik_CRXSecurityRock = (char *)KA_conf;
348     ubik_SRXSecurityProc = afsconf_ServerAuth;
349     ubik_SRXSecurityRock = (char *)KA_conf;
350     ubik_CheckRXSecurityProc = afsconf_CheckAuth;
351     ubik_CheckRXSecurityRock = (char *)KA_conf;
352
353     ubik_nBuffers = 80;
354
355     if (rxBind) {
356         afs_int32 ccode;
357         if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || 
358             AFSDIR_SERVER_NETINFO_FILEPATH) {
359             char reason[1024];
360             ccode = parseNetFiles(SHostAddrs, NULL, NULL,
361                                            ADDRSPERSITE, reason,
362                                            AFSDIR_SERVER_NETINFO_FILEPATH,
363                                            AFSDIR_SERVER_NETRESTRICT_FILEPATH);
364         } else 
365         {
366             ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
367         }
368         if (ccode == 1) {
369             host = SHostAddrs[0];
370             rx_InitHost(host, htons(AFSCONF_KAUTHPORT));
371         }
372     }
373
374     if (servers)
375         code =
376             ubik_ServerInit(myHost, htons(AFSCONF_KAUTHPORT), serverList,
377                             dbpath, &KA_dbase);
378     else
379         code =
380             ubik_ServerInitByInfo(myHost, htons(AFSCONF_KAUTHPORT), &cellinfo,
381                                   clones, dbpath, &KA_dbase);
382
383     if (code) {
384         afs_com_err(whoami, code, "Ubik init failed");
385         exit(2);
386     }
387
388     sca[RX_SCINDEX_NULL] = rxnull_NewServerSecurityObject();
389
390     /* Disable jumbograms */
391     rx_SetNoJumbo();
392
393     tservice =
394         rx_NewServiceHost(host, 0, KA_AUTHENTICATION_SERVICE, 
395                           "AuthenticationService", sca, 1, KAA_ExecuteRequest);
396     if (tservice == (struct rx_service *)0) {
397         ViceLog(0, ("Could not create Authentication rx service\n"));
398         exit(3);
399     }
400     rx_SetMinProcs(tservice, 1);
401     rx_SetMaxProcs(tservice, 1);
402
403     
404     tservice =
405         rx_NewServiceHost(host, 0, KA_TICKET_GRANTING_SERVICE, "TicketGrantingService",
406                       sca, 1, KAT_ExecuteRequest);
407     if (tservice == (struct rx_service *)0) {
408         ViceLog(0, ("Could not create Ticket Granting rx service\n"));
409         exit(3);
410     }
411     rx_SetMinProcs(tservice, 1);
412     rx_SetMaxProcs(tservice, 1);
413
414     scm[RX_SCINDEX_NULL] = sca[RX_SCINDEX_NULL];
415     scm[RX_SCINDEX_VAB] = 0;
416     scm[RX_SCINDEX_KAD] =
417         rxkad_NewServerSecurityObject(rxkad_crypt, 0, kvno_admin_key, 0);
418     tservice =
419         rx_NewServiceHost(host, 0, KA_MAINTENANCE_SERVICE, "Maintenance", scm, 3,
420                       KAM_ExecuteRequest);
421     if (tservice == (struct rx_service *)0) {
422         ViceLog(0, ("Could not create Maintenance rx service\n"));
423         exit(3);
424     }
425     rx_SetMinProcs(tservice, 1);
426     rx_SetMaxProcs(tservice, 1);
427     rx_SetStackSize(tservice, 10000);
428
429     tservice =
430         rx_NewServiceHost(host, 0, RX_STATS_SERVICE_ID, "rpcstats", scm, 3,
431                       RXSTATS_ExecuteRequest);
432     if (tservice == (struct rx_service *)0) {
433         ViceLog(0, ("Could not create rpc stats rx service\n"));
434         exit(3);
435     }
436     rx_SetMinProcs(tservice, 2);
437     rx_SetMaxProcs(tservice, 4);
438
439     initialize_dstats();
440
441     /* allow super users to manage RX statistics */
442     rx_SetRxStatUserOk(KA_rxstat_userok);
443
444     rx_StartServer(0);          /* start handling req. of all types */
445
446     if (init_kaprocs(lclpath, initFlags))
447         return -1;
448
449     if ((code = init_krb_udp())) {
450         ViceLog(0,
451                 ("Failed to initialize UDP interface; code = %d.\n", code));
452         ViceLog(0, ("Running without UDP access.\n"));
453     }
454
455     ViceLog(0, ("Starting to process AuthServer requests\n"));
456     rx_ServerProc(NULL);                /* donate this LWP */
457     return 0;
458 }