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