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