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