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