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