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