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