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