netrestrict-netinfo-20081129
[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             int tempfd, flags;
253             FILE *auditout;
254             char oldName[MAXPATHLEN];
255             char *fileName = argv[++a];
256             
257 #ifndef AFS_NT40_ENV
258             struct stat statbuf;
259             
260             if ((lstat(fileName, &statbuf) == 0) 
261                 && (S_ISFIFO(statbuf.st_mode))) {
262                 flags = O_WRONLY | O_NONBLOCK;
263             } else 
264 #endif
265             {
266                 strcpy(oldName, fileName);
267                 strcat(oldName, ".old");
268                 renamefile(fileName, oldName);
269                 flags = O_WRONLY | O_TRUNC | O_CREAT;
270             }
271             tempfd = open(fileName, flags, 0666);
272             if (tempfd > -1) {
273                 auditout = fdopen(tempfd, "a");
274                 if (auditout) {
275                     osi_audit_file(auditout);
276                 } else
277                     printf("Warning: auditlog %s not writable, ignored.\n", fileName);
278             } else
279                 printf("Warning: auditlog %s not writable, ignored.\n", fileName);
280         } else if (strcmp(arg, "-localfiles") == 0)
281             lclpath = argv[++a];
282         else if (strcmp(arg, "-servers") == 0)
283             debugOutput++, servers = 1;
284         else if (strcmp(arg, "-noauth") == 0)
285             debugOutput++, initFlags |= 1;
286         else if (strcmp(arg, "-fastkeys") == 0)
287             debugOutput++, initFlags |= 4;
288         else if (strcmp(arg, "-dbfixup") == 0)
289             debugOutput++, initFlags |= 8;
290         else if (strcmp(arg, "-cellservdb") == 0) {
291             cellservdb = argv[++a];
292             initFlags |= 2;
293             debugOutput++;
294         }
295
296         else if (IsArg("-crypt"))
297             level = rxkad_crypt;
298         else if (IsArg("-safe"))
299             level = rxkad_crypt;
300         else if (IsArg("-clear"))
301             level = rxkad_clear;
302         else if (IsArg("-sorry"))
303             level = rxkad_clear;
304         else if (IsArg("-debug"))
305             verbose_track = 0;
306         else if (IsArg("-crossrealm"))
307             krb4_cross = 1;
308         else if (IsArg("-rxbind"))
309             rxBind = 1;
310         else if (IsArg("-minhours")) {
311             MinHours = atoi(argv[++a]);
312         } else if (IsArg("-enable_peer_stats")) {
313             rx_enablePeerRPCStats();
314         } else if (IsArg("-enable_process_stats")) {
315             rx_enableProcessRPCStats();
316         } else if (*arg == '-') {
317             /* hack to support help flag */
318             goto usage;
319         }
320     }
321     if (code = ka_CellConfig(cellservdb))
322         goto abort;
323     cell = ka_LocalCell();
324     KA_conf = afsconf_Open(cellservdb);
325     if (!KA_conf) {
326         code = KANOCELLS;
327       abort:
328         afs_com_err(whoami, code, "Failed getting cell info");
329         exit(1);
330     }
331 #ifdef        AUTH_DBM_LOG
332     kalog_Init();
333 #else
334     /* NT & HPUX do not have dbm package support. So we can only do some
335      * text logging. So open the AuthLog file for logging and redirect
336      * stdin and stdout to it 
337      */
338     OpenLog(AFSDIR_SERVER_KALOG_FILEPATH);
339     SetupLogSignals();
340 #endif
341
342     fprintf(stderr, "%s: WARNING: kaserver is deprecated due to its weak security "
343             "properties.  Migrating to a Kerberos 5 KDC is advised.  "
344             "http://www.openafs.org/no-more-des.html\n", whoami);
345     ViceLog(0, ("WARNING: kaserver is deprecated due to its weak security properties.  "
346             "Migrating to a Kerberos 5 KDC is advised.  "
347             "http://www.openafs.org/no-more-des.html\n"));
348
349     code =
350         afsconf_GetExtendedCellInfo(KA_conf, cell, AFSCONF_KAUTHSERVICE,
351                                     &cellinfo, &clones);
352     if (servers) {
353         if (code = ubik_ParseServerList(argc, argv, &myHost, serverList)) {
354             afs_com_err(whoami, code, "Couldn't parse server list");
355             exit(1);
356         }
357         cellinfo.hostAddr[0].sin_addr.s_addr = myHost;
358         for (i = 1; i < MAXSERVERS; i++) {
359             if (!serverList[i])
360                 break;
361             cellinfo.hostAddr[i].sin_addr.s_addr = serverList[i];
362         }
363         cellinfo.numServers = i;
364     } else {
365         code = convert_cell_to_ubik(&cellinfo, &myHost, serverList);
366         if (code)
367             goto abort;
368         ViceLog(0, ("Using server list from %s cell database.\n", cell));
369     }
370
371     /* initialize ubik */
372     if (level == rxkad_clear)
373         ubik_CRXSecurityProc = afsconf_ClientAuth;
374     else if (level == rxkad_crypt)
375         ubik_CRXSecurityProc = afsconf_ClientAuthSecure;
376     else {
377         ViceLog(0, ("Unsupported security level %d\n", level));
378         exit(5);
379     }
380     ViceLog(0,
381             ("Using level %s for Ubik connections.\n",
382              (level == rxkad_crypt ? "crypt" : "clear")));
383     ubik_CRXSecurityRock = (char *)KA_conf;
384     ubik_SRXSecurityProc = afsconf_ServerAuth;
385     ubik_SRXSecurityRock = (char *)KA_conf;
386     ubik_CheckRXSecurityProc = afsconf_CheckAuth;
387     ubik_CheckRXSecurityRock = (char *)KA_conf;
388
389     ubik_nBuffers = 80;
390
391     if (rxBind) {
392         afs_int32 ccode;
393         if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || 
394             AFSDIR_SERVER_NETINFO_FILEPATH) {
395             char reason[1024];
396             ccode = parseNetFiles(SHostAddrs, NULL, NULL,
397                                            ADDRSPERSITE, reason,
398                                            AFSDIR_SERVER_NETINFO_FILEPATH,
399                                            AFSDIR_SERVER_NETRESTRICT_FILEPATH);
400         } else 
401         {
402             ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
403         }
404         if (ccode == 1) {
405             host = SHostAddrs[0];
406             rx_InitHost(host, htons(AFSCONF_KAUTHPORT));
407         }
408     }
409
410     if (servers)
411         code =
412             ubik_ServerInit(myHost, htons(AFSCONF_KAUTHPORT), serverList,
413                             dbpath, &KA_dbase);
414     else
415         code =
416             ubik_ServerInitByInfo(myHost, htons(AFSCONF_KAUTHPORT), &cellinfo,
417                                   &clones, dbpath, &KA_dbase);
418
419     if (code) {
420         afs_com_err(whoami, code, "Ubik init failed");
421         exit(2);
422     }
423
424     sca[RX_SCINDEX_NULL] = rxnull_NewServerSecurityObject();
425
426     /* Disable jumbograms */
427     rx_SetNoJumbo();
428
429     tservice =
430         rx_NewServiceHost(host, 0, KA_AUTHENTICATION_SERVICE, 
431                           "AuthenticationService", sca, 1, KAA_ExecuteRequest);
432     if (tservice == (struct rx_service *)0) {
433         ViceLog(0, ("Could not create Authentication rx service\n"));
434         exit(3);
435     }
436     rx_SetMinProcs(tservice, 1);
437     rx_SetMaxProcs(tservice, 1);
438
439     
440     tservice =
441         rx_NewServiceHost(host, 0, KA_TICKET_GRANTING_SERVICE, "TicketGrantingService",
442                       sca, 1, KAT_ExecuteRequest);
443     if (tservice == (struct rx_service *)0) {
444         ViceLog(0, ("Could not create Ticket Granting rx service\n"));
445         exit(3);
446     }
447     rx_SetMinProcs(tservice, 1);
448     rx_SetMaxProcs(tservice, 1);
449
450     scm[RX_SCINDEX_NULL] = sca[RX_SCINDEX_NULL];
451     scm[RX_SCINDEX_VAB] = 0;
452     scm[RX_SCINDEX_KAD] =
453         rxkad_NewServerSecurityObject(rxkad_crypt, 0, kvno_admin_key, 0);
454     tservice =
455         rx_NewServiceHost(host, 0, KA_MAINTENANCE_SERVICE, "Maintenance", scm, 3,
456                       KAM_ExecuteRequest);
457     if (tservice == (struct rx_service *)0) {
458         ViceLog(0, ("Could not create Maintenance rx service\n"));
459         exit(3);
460     }
461     rx_SetMinProcs(tservice, 1);
462     rx_SetMaxProcs(tservice, 1);
463     rx_SetStackSize(tservice, 10000);
464
465     tservice =
466         rx_NewServiceHost(host, 0, RX_STATS_SERVICE_ID, "rpcstats", scm, 3,
467                       RXSTATS_ExecuteRequest);
468     if (tservice == (struct rx_service *)0) {
469         ViceLog(0, ("Could not create rpc stats rx service\n"));
470         exit(3);
471     }
472     rx_SetMinProcs(tservice, 2);
473     rx_SetMaxProcs(tservice, 4);
474
475     initialize_dstats();
476
477     /* allow super users to manage RX statistics */
478     rx_SetRxStatUserOk(KA_rxstat_userok);
479
480     rx_StartServer(0);          /* start handling req. of all types */
481
482     if (init_kaprocs(lclpath, initFlags))
483         return -1;
484
485     if (code = init_krb_udp()) {
486         ViceLog(0,
487                 ("Failed to initialize UDP interface; code = %d.\n", code));
488         ViceLog(0, ("Running without UDP access.\n"));
489     }
490
491     ViceLog(0, ("Starting to process AuthServer requests\n"));
492     rx_ServerProc(NULL);                /* donate this LWP */
493     return 0;
494 }