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