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