2 * Copyright 2000, International Business Machines Corporation and others.
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
11 * A general description of the supergroup changes
14 * In AFS users can be members of groups. When you add
15 * a user, u1, to a group, g1, you add the user id for u1
16 * to an entries list in g1. This is a list of all the
18 * You also add the id for g1 to an entries list in u1.
19 * This is a list of all the groups this user is a
21 * The list has room for 10 entries. If more are required,
22 * a continuation record is created.
24 * With UMICH mods, u1 can be a group. When u1 is a group
25 * a new field is required to list the groups this group
26 * is a member of (since the entries field is used to
27 * list it's members). This new field is supergroups and
28 * has two entries. If more are required, a continuation
30 * There are two additional fields required, nextsg is
31 * an address of the next continuation record for this
32 * group, and countsg is the count for the number of
33 * groups this group is a member of.
37 * 09/18/95 jjm Add mdw's changes to afs-3.3a Changes:
38 * (1) Add the parameter -groupdepth or -depth to
39 * define the maximum search depth for supergroups.
40 * Define the variable depthsg to be the value of
41 * the parameter. The default value is set to 5.
43 * (3) Make sure the sizes of the struct prentry and
44 * struct prentryg are equal. If they aren't equal
45 * the pt database will be corrupted.
46 * The error is reported with an fprintf statement,
47 * but this doesn't print when ptserver is started by
48 * bos, so all you see is an error message in the
49 * /usr/afs/logs/BosLog file. If you start the
50 * ptserver without bos the fprintf will print
52 * The program will terminate with a PT_EXIT(1).
55 * Transarc does not currently use opcodes past 520, but
56 * they *could* decide at any time to use more opcodes.
57 * If they did, then one part of our local mods,
58 * ListSupergroups, would break. I've therefore
59 * renumbered it to 530, and put logic in to enable the
60 * old opcode to work (for now).
62 * 2/1/98 jjm Add mdw's changes for bit mapping for supergroups
64 * Before fetching a supergroup, this version of ptserver
65 * checks to see if it was marked "found" and "not a
66 * member". If and only if so, it doesn't fetch the group.
67 * Since this should be the case with most groups, this
68 * should save a significant amount of CPU in redundant
69 * fetches of the same group. After fetching the group,
70 * it sets "found", and either sets or clears "not a
71 * member", depending on if the group was a member of
72 * other groups. When it writes group entries to the
73 * database, it clears the "found" flag.
76 #if defined(SUPERGROUPS)
78 * A general description of the supergroup changes
81 * In AFS users can be members of groups. When you add a user, u1,
82 * to a group, g1, you add the user id for u1 to an entries list
83 * in g1. This is a list of all the members of g1. You also add
84 * the id for g1 to an entries list in u1. This is a list of all
85 * the groups this user is a member of. The list has room for 10
86 * entries. If more are required, a continuation record is created.
88 * With UMICH mods, u1 can be a group. When u1 is a group a new
89 * field is required to list the groups this group is a member of
90 * (since the entries field is used to list it's members). This
91 * new field is supergroups and has two entries. If more are
92 * required, a continuation record is formed.
94 * There are two additional fields required, nextsg is an address
95 * of the next continuation record for this group, and countsg is
96 * the count for the number of groups this group is a member of.
98 * Bit mapping support for supergroups:
100 * Before fetching a supergroup, this version of ptserver checks to
101 * see if it was marked "found" and "not a member". If and only if
102 * so, it doesn't fetch the group. Since this should be the case
103 * with most groups, this should save a significant amount of CPU in
104 * redundant fetches of the same group. After fetching the group, it
105 * sets "found", and either sets or clears "not a member", depending
106 * on if the group was a member of other groups. When it writes
107 * group entries to the database, it clears the "found" flag.
111 #include <afsconfig.h>
112 #include <afs/param.h>
115 #include <afs/stds.h>
119 #include <sys/types.h>
122 #include <sys/stat.h>
124 #include <winsock2.h>
125 #include <WINNT/afsevent.h>
128 #include <netinet/in.h>
133 #include <rx/rx_globals.h>
136 #include <afs/cellconfig.h>
137 #include <afs/auth.h>
138 #include <afs/keys.h>
139 #include "ptserver.h"
140 #include "ptprototypes.h"
141 #include "error_macros.h"
142 #include "afs/audit.h"
143 #include <afs/afsutil.h>
144 #include <afs/com_err.h>
145 #include <rx/rxstat.h>
147 /* make all of these into a structure if you want */
148 struct prheader cheader
;
149 struct ubik_dbase
*dbase
;
150 struct afsconf_dir
*prdir
;
152 #if defined(SUPERGROUPS)
153 extern afs_int32 depthsg
;
162 int rxkadDisableDotCheck
= 0;
164 #define ADDRSPERSITE 16 /* Same global is in rx/rx_user.c */
165 afs_uint32 SHostAddrs
[ADDRSPERSITE
];
167 static struct afsconf_cell info
;
169 extern int prp_group_default
;
170 extern int prp_user_default
;
172 #include "AFS_component_version_number.c"
175 prp_access_mask(char *s
)
178 if (*s
>= '0' && *s
<= '9') {
179 return strtol(s
, NULL
, 0);
182 while (*s
) switch(*s
++)
184 case 'S': r
|= PRP_STATUS_ANY
; break;
185 case 's': r
|= PRP_STATUS_MEM
; break;
186 case 'O': r
|= PRP_OWNED_ANY
; break;
187 case 'M': r
|= PRP_MEMBER_ANY
; break;
188 case 'm': r
|= PRP_MEMBER_MEM
; break;
189 case 'A': r
|= PRP_ADD_ANY
; break;
190 case 'a': r
|= PRP_ADD_MEM
; break;
191 case 'r': r
|= PRP_REMOVE_MEM
; break;
196 /* check whether caller is authorized to manage RX statistics */
198 pr_rxstat_userok(struct rx_call
*call
)
200 return afsconf_SuperUser(prdir
, call
, NULL
);
204 main(int argc
, char **argv
)
210 struct rx_service
*tservice
;
211 struct rx_securityClass
**securityClasses
;
212 afs_int32 numClasses
;
214 char clones
[MAXHOSTSPERCELL
];
215 afs_uint32 host
= htonl(INADDR_ANY
);
217 const char *pr_dbaseName
;
218 char *whoami
= "ptserver";
223 char *auditFileName
= NULL
;
227 * The following signal action for AIX is necessary so that in case of a
228 * crash (i.e. core is generated) we can include the user's data section
229 * in the core dump. Unfortunately, by default, only a partial core is
230 * generated which, in many cases, isn't too useful.
232 struct sigaction nsa
;
234 sigemptyset(&nsa
.sa_mask
);
235 nsa
.sa_handler
= SIG_DFL
;
236 nsa
.sa_flags
= SA_FULLDUMP
;
237 sigaction(SIGABRT
, &nsa
, NULL
);
238 sigaction(SIGSEGV
, &nsa
, NULL
);
241 osi_audit(PTS_StartEvent
, 0, AUD_END
);
243 /* Initialize dirpaths */
244 if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK
)) {
246 ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR
, 0, argv
[0], 0);
248 fprintf(stderr
, "%s: Unable to obtain AFS server directory.\n",
253 pr_dbaseName
= AFSDIR_SERVER_PRDB_FILEPATH
;
255 #if defined(SUPERGROUPS)
256 /* make sure the structures for database records are the same size */
257 if ((sizeof(struct prentry
) != ENTRYSIZE
)
258 || (sizeof(struct prentryg
) != ENTRYSIZE
)) {
260 "The structures for the database records are different"
261 " sizes\n" "struct prentry = %" AFS_SIZET_FMT
"\n"
262 "struct prentryg = %" AFS_SIZET_FMT
"\n"
263 "ENTRYSIZE = %d\n", sizeof(struct prentry
),
264 sizeof(struct prentryg
), ENTRYSIZE
);
269 for (a
= 1; a
< argc
; a
++) {
271 lcstring(arg
, argv
[a
], sizeof(arg
));
273 if (strcmp(argv
[a
], "-d") == 0) {
274 if ((a
+ 1) >= argc
) {
275 fprintf(stderr
, "missing argument for -d\n");
278 debuglevel
= atoi(argv
[++a
]);
279 LogLevel
= debuglevel
;
280 } else if ((strncmp(arg
, "-database", alen
) == 0)
281 || (strncmp(arg
, "-db", alen
) == 0)) {
282 pr_dbaseName
= argv
[++a
]; /* specify a database */
283 } else if (strncmp(arg
, "-p", alen
) == 0) {
284 lwps
= atoi(argv
[++a
]);
285 if (lwps
> 16) { /* maximum of 16 */
286 printf("Warning: '-p %d' is too big; using %d instead\n",
289 } else if (lwps
< 3) { /* minimum of 3 */
290 printf("Warning: '-p %d' is too small; using %d instead\n",
294 #if defined(SUPERGROUPS)
295 } else if ((strncmp(arg
, "-groupdepth", alen
) == 0)
296 || (strncmp(arg
, "-depth", alen
) == 0)) {
297 depthsg
= atoi(argv
[++a
]); /* Max search depth for supergroups */
299 } else if (strncmp(arg
, "-default_access", alen
) == 0) {
300 prp_user_default
= prp_access_mask(argv
[++a
]);
301 prp_group_default
= prp_access_mask(argv
[++a
]);
303 else if (strncmp(arg
, "-restricted", alen
) == 0) {
306 else if (strncmp(arg
, "-rxbind", alen
) == 0) {
309 else if (strncmp(arg
, "-allow-dotted-principals", alen
) == 0) {
310 rxkadDisableDotCheck
= 1;
312 else if (strncmp(arg
, "-enable_peer_stats", alen
) == 0) {
313 rx_enablePeerRPCStats();
314 } else if (strncmp(arg
, "-enable_process_stats", alen
) == 0) {
315 rx_enableProcessRPCStats();
318 else if (strncmp(arg
, "-syslog", alen
) == 0) {
319 /* set syslog logging flag */
321 } else if (strncmp(arg
, "-syslog=", MIN(8, alen
)) == 0) {
323 serverLogSyslogFacility
= atoi(arg
+ 8);
326 else if (strncmp(arg
, "-auditlog", alen
) == 0) {
327 auditFileName
= argv
[++a
];
329 } else if (strncmp(arg
, "-audit-interface", alen
) == 0) {
330 char *interface
= argv
[++a
];
331 if (osi_audit_interface(interface
)) {
332 printf("Invalid audit interface '%s'\n", interface
);
336 else if (!strncmp(arg
, "-rxmaxmtu", alen
)) {
337 if ((a
+ 1) >= argc
) {
338 fprintf(stderr
, "missing argument for -rxmaxmtu\n");
341 rxMaxMTU
= atoi(argv
[++a
]);
342 if ((rxMaxMTU
< RX_MIN_PACKET_SIZE
) ||
343 (rxMaxMTU
> RX_MAX_PACKET_DATA_SIZE
)) {
344 printf("rxMaxMTU %d invalid; must be between %d-%" AFS_SIZET_FMT
"\n",
345 rxMaxMTU
, RX_MIN_PACKET_SIZE
,
346 RX_MAX_PACKET_DATA_SIZE
);
350 else if (*arg
== '-') {
351 /* hack in help flag support */
353 #if defined(SUPERGROUPS)
355 printf("Usage: ptserver [-database <db path>] "
356 "[-auditlog <log path>] "
357 "[-audit-interface <file|sysvmq> (default is file)] "
358 "[-syslog[=FACILITY]] [-d <debug level>] "
359 "[-p <number of processes>] [-rebuild] "
360 "[-groupdepth <depth>] "
361 "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
362 "[-allow-dotted-principals] "
363 "[-enable_peer_stats] [-enable_process_stats] "
364 "[-default_access default_user_access default_group_access] "
366 #else /* AFS_NT40_ENV */
367 printf("Usage: ptserver [-database <db path>] "
368 "[-auditlog <log path>] "
369 "[-audit-interface <file|sysvmq> (default is file)] "
370 "[-d <debug level>] "
371 "[-p <number of processes>] [-rebuild] [-rxbind] "
372 "[-allow-dotted-principals] "
373 "[-default_access default_user_access default_group_access] "
374 "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
375 "[-groupdepth <depth>] " "[-help]\n");
379 printf("Usage: ptserver [-database <db path>] "
380 "[-auditlog <log path>] "
381 "[-audit-interface <file|sysvmq> (default is file)] "
382 "[-d <debug level>] "
383 "[-syslog[=FACILITY]] "
384 "[-p <number of processes>] [-rebuild] "
385 "[-enable_peer_stats] [-enable_process_stats] "
386 "[-default_access default_user_access default_group_access] "
387 "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
388 "[-allow-dotted-principals] "
390 #else /* AFS_NT40_ENV */
391 printf("Usage: ptserver [-database <db path>] "
392 "[-auditlog <log path>] [-d <debug level>] "
393 "[-default_access default_user_access default_group_access] "
394 "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
395 "[-allow-dotted-principals] "
396 "[-p <number of processes>] [-rebuild] " "[-help]\n");
403 #if defined(SUPERGROUPS)
405 fprintf(stderr
, "Unrecognized arg: '%s' ignored!\n", arg
);
411 osi_audit_file(auditFileName
);
412 osi_audit(PTS_StartEvent
, 0, AUD_END
);
416 serverLogSyslogTag
= "ptserver";
418 OpenLog(AFSDIR_SERVER_PTLOG_FILEPATH
); /* set up logging */
421 prdir
= afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH
);
423 fprintf(stderr
, "ptserver: can't open configuration directory.\n");
426 if (afsconf_GetNoAuthFlag(prdir
))
427 printf("ptserver: running unauthenticated\n");
430 /* initialize winsock */
431 if (afs_winsockInit() < 0) {
432 ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED
, 0, argv
[0], 0);
434 fprintf(stderr
, "ptserver: couldn't initialize winsock. \n");
439 gethostname(hostname
, sizeof(hostname
));
440 th
= gethostbyname(hostname
);
442 fprintf(stderr
, "ptserver: couldn't get address of this host.\n");
445 memcpy(&myHost
, th
->h_addr
, sizeof(afs_uint32
));
447 /* get list of servers */
449 afsconf_GetExtendedCellInfo(prdir
, NULL
, "afsprot", &info
, clones
);
451 afs_com_err(whoami
, code
, "Couldn't get server list");
454 pr_realmName
= info
.name
;
457 /* initialize ubik */
458 ubik_CRXSecurityProc
= afsconf_ClientAuth
;
459 ubik_CRXSecurityRock
= prdir
;
460 ubik_SRXSecurityProc
= afsconf_ServerAuth
;
461 ubik_SRXSecurityRock
= prdir
;
462 ubik_CheckRXSecurityProc
= afsconf_CheckAuth
;
463 ubik_CheckRXSecurityRock
= prdir
;
465 /* The max needed is when deleting an entry. A full CoEntry deletion
466 * required removal from 39 entries. Each of which may refers to the entry
467 * being deleted in one of its CoEntries. If a CoEntry is freed its
468 * predecessor CoEntry will be modified as well. Any freed blocks also
469 * modifies the database header. Counting the entry being deleted and its
470 * CoEntry this adds up to as much as 1+1+39*3 = 119. If all these entries
471 * and the header are in separate Ubik buffers then 120 buffers may be
473 ubik_nBuffers
= 120 + /*fudge */ 40;
477 if (AFSDIR_SERVER_NETRESTRICT_FILEPATH
||
478 AFSDIR_SERVER_NETINFO_FILEPATH
) {
480 ccode
= parseNetFiles(SHostAddrs
, NULL
, NULL
,
481 ADDRSPERSITE
, reason
,
482 AFSDIR_SERVER_NETINFO_FILEPATH
,
483 AFSDIR_SERVER_NETRESTRICT_FILEPATH
);
486 ccode
= rx_getAllAddr(SHostAddrs
, ADDRSPERSITE
);
489 host
= SHostAddrs
[0];
490 /* the following call is idempotent so if/when it gets called
491 * again by the ubik init stuff, it doesn't really matter
494 rx_InitHost(host
, htons(AFSCONF_PROTPORT
));
498 /* Disable jumbograms */
501 if (rxMaxMTU
!= -1) {
502 rx_SetMaxMTU(rxMaxMTU
);
506 ubik_ServerInitByInfo(myHost
, htons(AFSCONF_PROTPORT
), &info
, clones
,
507 pr_dbaseName
, &dbase
);
509 afs_com_err(whoami
, code
, "Ubik init failed");
512 #if defined(SUPERGROUPS)
516 afsconf_BuildServerSecurityObjects(prdir
, 0, &securityClasses
,
520 rx_NewServiceHost(host
, 0, PRSRV
, "Protection Server", securityClasses
,
521 numClasses
, PR_ExecuteRequest
);
522 if (tservice
== (struct rx_service
*)0) {
523 fprintf(stderr
, "ptserver: Could not create new rx service.\n");
526 rx_SetMinProcs(tservice
, 2);
527 rx_SetMaxProcs(tservice
, lwps
);
528 if (rxkadDisableDotCheck
) {
529 rx_SetSecurityConfiguration(tservice
, RXS_CONFIG_FLAGS
,
530 (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK
);
534 rx_NewServiceHost(host
, 0, RX_STATS_SERVICE_ID
, "rpcstats",
535 securityClasses
, numClasses
, RXSTATS_ExecuteRequest
);
536 if (tservice
== (struct rx_service
*)0) {
537 fprintf(stderr
, "ptserver: Could not create new rx service.\n");
540 rx_SetMinProcs(tservice
, 2);
541 rx_SetMaxProcs(tservice
, 4);
543 /* allow super users to manage RX statistics */
544 rx_SetRxStatUserOk(pr_rxstat_userok
);
546 LogCommandLine(argc
, argv
, "ptserver",
547 #if defined(SUPERGROUPS)
552 "Starting AFS", FSLog
);
553 if (afsconf_GetLatestKey(prdir
, NULL
, NULL
) == 0) {
558 osi_audit(PTS_FinishEvent
, -1, AUD_END
);