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