fb7fa725edc4291e0ba1c3a790588f0dc52f2f4f
[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
13 RCSID
14     ("$Header$");
15
16 #include <afs/stds.h>
17 #include <sys/types.h>
18 #ifdef AFS_NT40_ENV
19 #include <winsock2.h>
20 #include <WINNT/afsevent.h>
21 #else
22 #include <sys/file.h>
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #endif
26 #include "kalog.h"              /* for OpenLog() */
27 #include <time.h>
28 #include <stdio.h>
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #else
32 #ifdef HAVE_STRINGS_H
33 #include <strings.h>
34 #endif
35 #endif
36 #ifdef HAVE_FCNTL_H
37 #include <fcntl.h>
38 #endif
39 #ifdef  AFS_AIX32_ENV
40 #include <signal.h>
41 #endif
42 #include <lwp.h>
43 #include <rx/xdr.h>
44 #include <rx/rx.h>
45 #include <rx/rxkad.h>
46 #include <rx/rx_globals.h>
47 #include <afs/cellconfig.h>
48 #include <lock.h>
49 #include <afs/afsutil.h>
50 #include <ubik.h>
51 #include "kauth.h"
52 #include "kautils.h"
53 #include "kaserver.h"
54
55
56 struct kadstats dynamic_statistics;
57 struct ubik_dbase *KA_dbase;
58 afs_int32 myHost = 0;
59 afs_int32 verbose_track = 1;
60 afs_int32 krb4_cross = 0;
61
62 struct afsconf_dir *KA_conf;    /* for getting cell info */
63
64 int MinHours = 0;
65 int npwSums = KA_NPWSUMS;       /* needs to be variable sometime */
66
67 #include <stdarg.h>
68 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
69 #undef vfprintf
70 #define vfprintf(stream,fmt,args) _doprnt(fmt,args,stream)
71 #endif
72
73 static int debugOutput;
74
75 /* check whether caller is authorized to manage RX statistics */
76 int
77 KA_rxstat_userok(call)
78      struct rx_call *call;
79 {
80     return afsconf_SuperUser(KA_conf, call, NULL);
81 }
82
83 afs_int32
84 es_Report(char *fmt, ...)
85 {
86     va_list pvar;
87
88     if (debugOutput == 0)
89         return 0;
90     va_start(pvar, fmt);
91     vfprintf(stderr, fmt, pvar);
92     va_end(pvar);
93     return 0;
94 }
95
96 static void
97 initialize_dstats()
98 {
99     memset(&dynamic_statistics, 0, sizeof(dynamic_statistics));
100     dynamic_statistics.start_time = time(0);
101     dynamic_statistics.host = myHost;
102 }
103
104 static int
105 convert_cell_to_ubik(cellinfo, myHost, serverList)
106      struct afsconf_cell *cellinfo;
107      afs_int32 *myHost;
108      afs_int32 *serverList;
109 {
110     int i;
111     char hostname[64];
112     struct hostent *th;
113
114     /* get this host */
115     gethostname(hostname, sizeof(hostname));
116     th = gethostbyname(hostname);
117     if (!th) {
118         ViceLog(0, ("kaserver: couldn't get address of this host.\n"));
119         exit(1);
120     }
121     memcpy(myHost, th->h_addr, sizeof(afs_int32));
122
123     for (i = 0; i < cellinfo->numServers; i++)
124         if (cellinfo->hostAddr[i].sin_addr.s_addr != *myHost) {
125             /* omit my host from serverList */
126             *serverList++ = cellinfo->hostAddr[i].sin_addr.s_addr;
127         }
128     *serverList = 0;            /* terminate list */
129     return 0;
130 }
131
132 static afs_int32
133 kvno_admin_key(rock, kvno, key)
134      char *rock;
135      afs_int32 kvno;
136      struct ktc_encryptionKey *key;
137 {
138     return ka_LookupKvno(0, KA_ADMIN_NAME, KA_ADMIN_INST, kvno, key);
139
140     /* we would like to start a Ubik transaction to fill the cache if that
141      * fails, but may deadlock as Rx is now organized. */
142 }
143
144 /* initFlags: 0x01  Do not require authenticated connections.
145               0x02  Do not check the bos NoAuth flag
146               0x04  Use fast key expiration to test oldkey code.
147               0x08  Temporary flag allowing database inconsistency fixup
148  */
149
150 #include "AFS_component_version_number.c"
151
152 main(argc, argv)
153      int argc;
154      char *argv[];
155 {
156     afs_int32 code;
157     char *whoami = argv[0];
158     afs_int32 serverList[MAXSERVERS];
159     struct afsconf_cell cellinfo;
160     char *cell;
161     const char *cellservdb, *dbpath, *lclpath;
162     int a;
163     char arg[32];
164     char default_lclpath[AFSDIR_PATH_MAX];
165     int servers;
166     int initFlags;
167     int level;                  /* security level for Ubik */
168     afs_int32 i;
169     char clones[MAXHOSTSPERCELL];
170
171     struct rx_service *tservice;
172     struct rx_securityClass *sca[1];
173     struct rx_securityClass *scm[3];
174
175     extern int afsconf_ClientAuthSecure();
176     extern int afsconf_ServerAuth();
177     extern int afsconf_CheckAuth();
178
179     extern int rx_stackSize;
180     extern int KAA_ExecuteRequest();
181     extern int KAT_ExecuteRequest();
182     extern int KAM_ExecuteRequest();
183     extern int RXSTATS_ExecuteRequest();
184
185 #ifdef  AFS_AIX32_ENV
186     /*
187      * The following signal action for AIX is necessary so that in case of a 
188      * crash (i.e. core is generated) we can include the user's data section 
189      * in the core dump. Unfortunately, by default, only a partial core is
190      * generated which, in many cases, isn't too useful.
191      */
192     struct sigaction nsa;
193
194     sigemptyset(&nsa.sa_mask);
195     nsa.sa_handler = SIG_DFL;
196     nsa.sa_flags = SA_FULLDUMP;
197     sigaction(SIGABRT, &nsa, NULL);
198     sigaction(SIGSEGV, &nsa, NULL);
199 #endif
200     if (argc == 0) {
201       usage:
202         printf("Usage: kaserver [-noAuth] [-fastKeys] [-database <dbpath>] "
203                "[-localfiles <lclpath>] [-minhours <n>] [-servers <serverlist>] "
204                "[-crossrealm]"
205                /*" [-enable_peer_stats] [-enable_process_stats] " */
206                "[-help]\n");
207         exit(1);
208     }
209 #ifdef AFS_NT40_ENV
210     /* initialize winsock */
211     if (afs_winsockInit() < 0) {
212         ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);
213         fprintf(stderr, "%s: Couldn't initialize winsock.\n", whoami);
214         exit(1);
215     }
216 #endif
217     /* Initialize dirpaths */
218     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
219 #ifdef AFS_NT40_ENV
220         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
221 #endif
222         fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
223                 argv[0]);
224         exit(2);
225     }
226
227     cellservdb = AFSDIR_SERVER_ETC_DIRPATH;
228     dbpath = AFSDIR_SERVER_KADB_FILEPATH;
229     strcompose(default_lclpath, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH,
230                "/", AFSDIR_KADB_FILE, NULL);
231     lclpath = default_lclpath;
232
233     debugOutput = 0;
234     servers = 0;
235     initFlags = 0;
236     level = rxkad_crypt;
237     for (a = 1; a < argc; a++) {
238         int arglen = strlen(argv[a]);
239         lcstring(arg, argv[a], sizeof(arg));
240 #define IsArg(a) (strncmp (arg,a, arglen) == 0)
241
242         if (strcmp(arg, "-database") == 0) {
243             dbpath = argv[++a];
244             if (strcmp(lclpath, default_lclpath) == 0)
245                 lclpath = dbpath;
246         } else if (strcmp(arg, "-localfiles") == 0)
247             lclpath = argv[++a];
248         else if (strcmp(arg, "-servers") == 0)
249             debugOutput++, servers = 1;
250         else if (strcmp(arg, "-noauth") == 0)
251             debugOutput++, initFlags |= 1;
252         else if (strcmp(arg, "-fastkeys") == 0)
253             debugOutput++, initFlags |= 4;
254         else if (strcmp(arg, "-dbfixup") == 0)
255             debugOutput++, initFlags |= 8;
256         else if (strcmp(arg, "-cellservdb") == 0) {
257             cellservdb = argv[++a];
258             initFlags |= 2;
259             debugOutput++;
260         }
261
262         else if (IsArg("-crypt"))
263             level = rxkad_crypt;
264         else if (IsArg("-safe"))
265             level = rxkad_crypt;
266         else if (IsArg("-clear"))
267             level = rxkad_clear;
268         else if (IsArg("-sorry"))
269             level = rxkad_clear;
270         else if (IsArg("-debug"))
271             verbose_track = 0;
272         else if (IsArg("-crossrealm"))
273             krb4_cross = 1;
274         else if (IsArg("-minhours")) {
275             MinHours = atoi(argv[++a]);
276         } else if (IsArg("-enable_peer_stats")) {
277             rx_enablePeerRPCStats();
278         } else if (IsArg("-enable_process_stats")) {
279             rx_enableProcessRPCStats();
280         } else if (*arg == '-') {
281             /* hack to support help flag */
282             goto usage;
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         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     code =
306         afsconf_GetExtendedCellInfo(KA_conf, cell, AFSCONF_KAUTHSERVICE,
307                                     &cellinfo, &clones);
308     if (servers) {
309         if (code = ubik_ParseServerList(argc, argv, &myHost, serverList)) {
310             com_err(whoami, code, "Couldn't parse server list");
311             exit(1);
312         }
313         cellinfo.hostAddr[0].sin_addr.s_addr = myHost;
314         for (i = 1; i < MAXSERVERS; i++) {
315             if (!serverList[i])
316                 break;
317             cellinfo.hostAddr[i].sin_addr.s_addr = serverList[i];
318         }
319         cellinfo.numServers = i;
320     } else {
321         code = convert_cell_to_ubik(&cellinfo, &myHost, serverList);
322         if (code)
323             goto abort;
324         ViceLog(0, ("Using server list from %s cell database.\n", cell));
325     }
326
327     /* initialize ubik */
328     if (level == rxkad_clear)
329         ubik_CRXSecurityProc = afsconf_ClientAuth;
330     else if (level == rxkad_crypt)
331         ubik_CRXSecurityProc = afsconf_ClientAuthSecure;
332     else {
333         ViceLog(0, ("Unsupported security level %d\n", level));
334         exit(5);
335     }
336     ViceLog(0,
337             ("Using level %s for Ubik connections.\n",
338              (level == rxkad_crypt ? "crypt" : "clear")));
339     ubik_CRXSecurityRock = (char *)KA_conf;
340     ubik_SRXSecurityProc = afsconf_ServerAuth;
341     ubik_SRXSecurityRock = (char *)KA_conf;
342     ubik_CheckRXSecurityProc = afsconf_CheckAuth;
343     ubik_CheckRXSecurityRock = (char *)KA_conf;
344
345     ubik_nBuffers = 80;
346     if (servers)
347         code =
348             ubik_ServerInit(myHost, htons(AFSCONF_KAUTHPORT), serverList,
349                             dbpath, &KA_dbase);
350     else
351         code =
352             ubik_ServerInitByInfo(myHost, htons(AFSCONF_KAUTHPORT), &cellinfo,
353                                   &clones, dbpath, &KA_dbase);
354
355     if (code) {
356         com_err(whoami, code, "Ubik init failed");
357         exit(2);
358     }
359
360     sca[RX_SCINDEX_NULL] = rxnull_NewServerSecurityObject();
361
362     /* Disable jumbograms */
363     rx_SetNoJumbo();
364
365     tservice =
366         rx_NewService(0, KA_AUTHENTICATION_SERVICE, "AuthenticationService",
367                       sca, 1, KAA_ExecuteRequest);
368     if (tservice == (struct rx_service *)0) {
369         ViceLog(0, ("Could not create Authentication rx service\n"));
370         exit(3);
371     }
372     rx_SetMinProcs(tservice, 1);
373     rx_SetMaxProcs(tservice, 1);
374
375     tservice =
376         rx_NewService(0, KA_TICKET_GRANTING_SERVICE, "TicketGrantingService",
377                       sca, 1, KAT_ExecuteRequest);
378     if (tservice == (struct rx_service *)0) {
379         ViceLog(0, ("Could not create Ticket Granting rx service\n"));
380         exit(3);
381     }
382     rx_SetMinProcs(tservice, 1);
383     rx_SetMaxProcs(tservice, 1);
384
385     scm[RX_SCINDEX_NULL] = sca[RX_SCINDEX_NULL];
386     scm[RX_SCINDEX_VAB] = 0;
387     scm[RX_SCINDEX_KAD] =
388         rxkad_NewServerSecurityObject(rxkad_crypt, 0, kvno_admin_key, 0);
389     tservice =
390         rx_NewService(0, KA_MAINTENANCE_SERVICE, "Maintenance", scm, 3,
391                       KAM_ExecuteRequest);
392     if (tservice == (struct rx_service *)0) {
393         ViceLog(0, ("Could not create Maintenance rx service\n"));
394         exit(3);
395     }
396     rx_SetMinProcs(tservice, 1);
397     rx_SetMaxProcs(tservice, 1);
398     rx_SetStackSize(tservice, 10000);
399
400     tservice =
401         rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", scm, 3,
402                       RXSTATS_ExecuteRequest);
403     if (tservice == (struct rx_service *)0) {
404         ViceLog(0, ("Could not create rpc stats rx service\n"));
405         exit(3);
406     }
407     rx_SetMinProcs(tservice, 2);
408     rx_SetMaxProcs(tservice, 4);
409
410     initialize_dstats();
411
412     /* allow super users to manage RX statistics */
413     rx_SetRxStatUserOk(KA_rxstat_userok);
414
415     rx_StartServer(0);          /* start handling req. of all types */
416
417     if (init_kaprocs(lclpath, initFlags))
418         return -1;
419
420     if (code = init_krb_udp()) {
421         ViceLog(0,
422                 ("Failed to initialize UDP interface; code = %d.\n", code));
423         ViceLog(0, ("Running without UDP access.\n"));
424     }
425
426     ViceLog(0, ("Starting to process AuthServer requests\n"));
427     rx_ServerProc();            /* donate this LWP */
428     return 0;
429 }