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