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