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