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