pull-prototypes-to-head-20020821
[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, NULL);
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 int KAA_ExecuteRequest();
173     extern int KAT_ExecuteRequest();
174     extern int KAM_ExecuteRequest();
175     extern int RXSTATS_ExecuteRequest();
176
177 #ifdef  AFS_AIX32_ENV
178     /*
179      * The following signal action for AIX is necessary so that in case of a 
180      * crash (i.e. core is generated) we can include the user's data section 
181      * in the core dump. Unfortunately, by default, only a partial core is
182      * generated which, in many cases, isn't too useful.
183      */
184     struct sigaction nsa;
185     
186     sigemptyset(&nsa.sa_mask);
187     nsa.sa_handler = SIG_DFL;
188     nsa.sa_flags = SA_FULLDUMP;
189     sigaction(SIGABRT, &nsa, NULL);
190     sigaction(SIGSEGV, &nsa, NULL);
191 #endif
192     if (argc == 0) {
193       usage:
194         printf("Usage: kaserver [-noAuth] [-fastKeys] [-database <dbpath>] "
195                "[-localfiles <lclpath>] [-minhours <n>] [-servers <serverlist>] "
196                /*" [-enable_peer_stats] [-enable_process_stats] " */
197                "[-help]\n");
198         exit(1);
199     }
200 #ifdef AFS_NT40_ENV
201     /* initialize winsock */
202     if (afs_winsockInit()<0) {
203       ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0,
204                           argv[0],0);
205       fprintf(stderr, "%s: Couldn't initialize winsock.\n", whoami);
206       exit(1);
207     }
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", argv[0]);
215         exit(2);
216     }
217
218     cellservdb = AFSDIR_SERVER_ETC_DIRPATH;
219     dbpath = AFSDIR_SERVER_KADB_FILEPATH;
220     strcompose(default_lclpath, AFSDIR_PATH_MAX,
221                AFSDIR_SERVER_LOCAL_DIRPATH, "/", AFSDIR_KADB_FILE, NULL);
222     lclpath = default_lclpath;
223
224     debugOutput = 0;
225     servers = 0;
226     initFlags = 0;
227     level = rxkad_crypt;
228     for (a=1; a<argc; a++) {
229         int arglen = strlen(argv[a]);
230         lcstring (arg, argv[a], sizeof(arg));
231 #define IsArg(a) (strncmp (arg,a, arglen) == 0)
232
233         if (strcmp (arg, "-database") == 0) {
234             dbpath = argv[++a];
235             if (strcmp(lclpath, default_lclpath) == 0) lclpath = dbpath;
236         }
237         else if (strcmp (arg, "-localfiles") == 0) lclpath = argv[++a];
238         else if (strcmp (arg, "-servers") == 0) debugOutput++, servers = 1;
239         else if (strcmp (arg, "-noauth") == 0) debugOutput++, initFlags |= 1;
240         else if (strcmp (arg, "-fastkeys") == 0) debugOutput++, initFlags |= 4;
241         else if (strcmp (arg, "-dbfixup") == 0) debugOutput++, initFlags |= 8;
242         else if (strcmp (arg, "-cellservdb") == 0) {
243             cellservdb = argv[++a];
244             initFlags |= 2;
245             debugOutput++;
246         }
247
248         else if (IsArg("-crypt")) level = rxkad_crypt;
249         else if (IsArg("-safe")) level = rxkad_crypt;
250         else if (IsArg("-clear")) level = rxkad_clear;
251         else if (IsArg("-sorry")) level = rxkad_clear;
252         else if (IsArg("-debug")) verbose_track = 0;
253         else if (IsArg("-minhours")) {
254              MinHours = atoi(argv[++a]);
255         }
256         else if (IsArg("-enable_peer_stats")) {
257             rx_enablePeerRPCStats();
258         }
259         else if (IsArg("-enable_process_stats")) {
260             rx_enableProcessRPCStats();
261         }
262         else if (*arg == '-') {
263                 /* hack to support help flag */
264             goto usage;
265         }
266     }
267     if (code = ka_CellConfig (cellservdb)) goto abort;
268     cell = ka_LocalCell();
269     KA_conf = afsconf_Open (cellservdb);
270     if (!KA_conf) {
271         code = KANOCELLS;
272       abort:
273         com_err (whoami, code, "Failed getting cell info");
274         exit (1);
275     }
276 #ifdef        AUTH_DBM_LOG
277     kalog_Init();
278 #else
279     /* NT & HPUX do not have dbm package support. So we can only do some
280      * text logging. So open the AuthLog file for logging and redirect
281      * stdin and stdout to it 
282      */
283     OpenLog(AFSDIR_SERVER_KALOG_FILEPATH); 
284     SetupLogSignals();
285 #endif
286     code = afsconf_GetExtendedCellInfo (KA_conf, cell, AFSCONF_KAUTHSERVICE,
287                                     &cellinfo, &clones);
288     if (servers) {
289         if (code = ubik_ParseServerList(argc, argv, &myHost, serverList)) {
290             com_err(whoami, code, "Couldn't parse server list");
291             exit(1);
292         }
293         cellinfo.hostAddr[0].sin_addr.s_addr = myHost;
294         for (i=1; i<MAXSERVERS; i++) {
295             if (!serverList[i]) break;
296             cellinfo.hostAddr[i].sin_addr.s_addr = serverList[i];
297         }
298         cellinfo.numServers = i;
299     }
300     else {
301         code = convert_cell_to_ubik (&cellinfo, &myHost, serverList);
302         if (code) goto abort;
303         ViceLog (0, ("Using server list from %s cell database.\n", cell));
304     }
305
306     /* initialize ubik */
307     if (level == rxkad_clear)
308         ubik_CRXSecurityProc = afsconf_ClientAuth;
309     else if (level == rxkad_crypt)
310         ubik_CRXSecurityProc = afsconf_ClientAuthSecure;
311     else {
312         ViceLog(0, ("Unsupported security level %d\n", level));
313         exit (5);
314     }
315     ViceLog (0, ("Using level %s for Ubik connections.\n", (level == rxkad_crypt ? "crypt": "clear")));
316     ubik_CRXSecurityRock = (char *)KA_conf;
317     ubik_SRXSecurityProc = afsconf_ServerAuth;
318     ubik_SRXSecurityRock = (char *)KA_conf;
319     ubik_CheckRXSecurityProc = afsconf_CheckAuth;
320     ubik_CheckRXSecurityRock = (char *)KA_conf;
321
322     ubik_nBuffers = 80;
323     if (servers)
324         code = ubik_ServerInit (myHost, htons(AFSCONF_KAUTHPORT), serverList,
325                             dbpath, &KA_dbase);
326     else
327         code = ubik_ServerInitByInfo (myHost, htons(AFSCONF_KAUTHPORT), 
328                            &cellinfo, &clones, dbpath, &KA_dbase);
329
330     if (code) {
331         com_err(whoami, code, "Ubik init failed");
332         exit(2);
333     }
334
335     sca[RX_SCINDEX_NULL] = rxnull_NewServerSecurityObject();
336
337     /* Disable jumbograms */
338     rx_SetNoJumbo();
339
340     tservice =
341         rx_NewService (0, KA_AUTHENTICATION_SERVICE, "AuthenticationService",
342                        sca, 1, KAA_ExecuteRequest);
343     if (tservice == (struct rx_service *)0) {
344         ViceLog(0, ("Could not create Authentication rx service\n"));
345         exit(3);
346     }
347     rx_SetMinProcs(tservice, 1);
348     rx_SetMaxProcs(tservice, 1);
349
350     tservice =
351         rx_NewService (0, KA_TICKET_GRANTING_SERVICE, "TicketGrantingService",
352                        sca, 1, KAT_ExecuteRequest);
353     if (tservice == (struct rx_service *)0) {
354         ViceLog(0, ("Could not create Ticket Granting rx service\n"));
355         exit(3);
356     }
357     rx_SetMinProcs(tservice, 1);
358     rx_SetMaxProcs(tservice, 1);
359
360     scm[RX_SCINDEX_NULL] = sca[RX_SCINDEX_NULL];
361     scm[RX_SCINDEX_VAB] = 0;
362     scm[RX_SCINDEX_KAD] =
363         rxkad_NewServerSecurityObject (rxkad_crypt, 0, kvno_admin_key, 0);
364     tservice = rx_NewService(0, KA_MAINTENANCE_SERVICE, "Maintenance",
365                              scm, 3, KAM_ExecuteRequest);
366     if (tservice == (struct rx_service *)0) {
367         ViceLog(0, ("Could not create Maintenance rx service\n"));
368         exit(3);
369     }
370     rx_SetMinProcs(tservice, 1);
371     rx_SetMaxProcs(tservice, 1);
372     rx_SetStackSize(tservice, 10000);
373
374     tservice =
375         rx_NewService (0, RX_STATS_SERVICE_ID, "rpcstats",
376                        scm, 3, RXSTATS_ExecuteRequest);
377     if (tservice == (struct rx_service *)0) {
378         ViceLog(0, ("Could not create rpc stats rx service\n"));
379         exit(3);
380     }
381     rx_SetMinProcs(tservice, 2);
382     rx_SetMaxProcs(tservice, 4);
383
384     initialize_dstats();
385
386     /* allow super users to manage RX statistics */
387     rx_SetRxStatUserOk(KA_rxstat_userok);
388
389     rx_StartServer(0);                  /* start handling req. of all types */
390
391     if (init_kaprocs (lclpath, initFlags)) return -1;
392
393     if (code = init_krb_udp()) {
394         ViceLog (0, ("Failed to initialize UDP interface; code = %d.\n", code));
395         ViceLog (0, ("Running without UDP access.\n"));
396     }
397
398     ViceLog (0, ("Starting to process AuthServer requests\n"));
399     rx_ServerProc();                    /* donate this LWP */
400 }