3bb2cf37bb89885e095e637d656c42c5fa692785
[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 /*
11  * Revision 2.3  1991/12/30  20:36:46
12  * #837: Added AuthLog support for the kaserver
13  *
14  * Revision 2.2  90/08/29  15:10:50
15  * Cleanups.
16  * Don't create rxvab security object.
17  * 
18  * Revision 2.1  90/08/07  19:11:30
19  * Start with clean version to sync test and dev trees.
20  * */
21
22 #include <afs/param.h>
23 #include <afs/stds.h>
24 #include <sys/types.h>
25 #ifdef AFS_NT40_ENV
26 #include <fcntl.h>
27 #include <winsock2.h>
28 #include <WINNT/afsevent.h>
29 #else
30 #include <sys/file.h>
31 #include <netdb.h>
32 #include <netinet/in.h>
33 #endif
34 #include "kalog.h"           /* for OpenLog() */
35 #include <time.h>
36 #include <stdio.h>
37 #ifdef  AFS_AIX32_ENV
38 #include <signal.h>
39 #endif
40 #include <lwp.h>
41 #include <rx/xdr.h>
42 #include <rx/rx.h>
43 #include <rx/rxkad.h>
44 #include <rx/rx_globals.h>
45 #include <afs/cellconfig.h>
46 #include <lock.h>
47 #include <afs/afsutil.h>
48 #include <ubik.h>
49 #include "kauth.h"
50 #include "kautils.h"
51 #include "kaserver.h"
52
53
54 struct kadstats dynamic_statistics;
55 struct ubik_dbase *KA_dbase;
56 afs_int32 myHost = 0;
57 afs_int32 verbose_track = 1;
58 struct afsconf_dir *KA_conf;            /* for getting cell info */
59
60 extern afs_int32 ubik_lastYesTime;
61 extern afs_int32 ubik_nBuffers;
62 int MinHours = 0;
63 int npwSums = KA_NPWSUMS;               /* needs to be variable sometime */
64
65 #include <stdarg.h>
66 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV)
67 #undef vfprintf
68 #define vfprintf(stream,fmt,args) _doprnt(fmt,args,stream)
69 #endif
70
71 static int debugOutput;
72
73 /* check whether caller is authorized to manage RX statistics */
74 int KA_rxstat_userok(call)
75     struct rx_call *call;
76 {
77     return afsconf_SuperUser(KA_conf, call, (char *)0);
78 }
79
80 afs_int32 es_Report(char *fmt, ...)
81 {
82     va_list pvar;
83
84     if (debugOutput == 0) return 0;
85     va_start (pvar, fmt);
86     vfprintf (stderr, fmt, pvar);
87     va_end(pvar);
88     return 0;
89 }
90
91 static void initialize_dstats ()
92 {
93     bzero (&dynamic_statistics, sizeof(dynamic_statistics));
94     dynamic_statistics.start_time = time(0);
95     dynamic_statistics.host = myHost;
96 }
97
98 static int convert_cell_to_ubik (cellinfo, myHost, serverList)
99   struct afsconf_cell *cellinfo;
100   afs_int32                   *myHost;
101   afs_int32                   *serverList;
102 {   int  i;
103     char hostname[64];
104     struct hostent *th;
105
106     /* get this host */
107     gethostname(hostname,sizeof(hostname));
108     th = gethostbyname(hostname);
109     if (!th) {
110         ViceLog(0, ("kaserver: couldn't get address of this host.\n"));
111         exit(1);
112     }
113     bcopy(th->h_addr,myHost,sizeof(afs_int32));
114
115     for (i=0; i<cellinfo->numServers; i++)
116         if (cellinfo->hostAddr[i].sin_addr.s_addr != *myHost) {
117             /* omit my host from serverList */
118             *serverList++ = cellinfo->hostAddr[i].sin_addr.s_addr;
119         }
120     *serverList = 0;                    /* terminate list */
121     return 0;
122 }
123
124 static afs_int32 kvno_admin_key (rock, kvno, key)
125   char *rock;
126   afs_int32  kvno;
127   struct ktc_encryptionKey *key;
128 {
129     return ka_LookupKvno (0, KA_ADMIN_NAME, KA_ADMIN_INST, kvno, key);
130
131     /* we would like to start a Ubik transaction to fill the cache if that
132        fails, but may deadlock as Rx is now organized. */
133 }
134
135 /* initFlags: 0x01  Do not require authenticated connections.
136               0x02  Do not check the bos NoAuth flag
137               0x04  Use fast key expiration to test oldkey code.
138               0x08  Temporary flag allowing database inconsistency fixup
139  */
140
141 #include "AFS_component_version_number.c"
142
143 main (argc, argv)
144   int   argc;
145   char *argv[];
146 {
147     afs_int32  code;
148     char *whoami = argv[0];
149     afs_int32  serverList[MAXSERVERS];
150     struct afsconf_cell  cellinfo;
151     char *cell;
152     const char *cellservdb, *dbpath, *lclpath;
153     int   a;
154     char  arg[32];
155     char  default_lclpath[AFSDIR_PATH_MAX];
156     int   servers;
157     int   initFlags;
158     int   level;                        /* security level for Ubik */
159     afs_int32 i;
160     char  clones[MAXHOSTSPERCELL];
161
162     struct rx_service *tservice;
163     struct rx_securityClass *sca[1];
164     struct rx_securityClass *scm[3];
165     
166     extern int afsconf_ClientAuth();
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 }