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>
113 #include <afs/stds.h>
117 #ifdef AFS_PTHREAD_ENV
118 # include <opr/softsig.h>
119 # include <afs/procmgmt_softsig.h> /* must come after softsig.h */
123 #include <WINNT/afsevent.h>
128 #include <rx/rx_globals.h>
129 #include <rx/rxstat.h>
133 #include <afs/cellconfig.h>
134 #include <afs/auth.h>
135 #include <afs/keys.h>
136 #include <afs/afsutil.h>
137 #include <afs/audit.h>
138 #include <afs/com_err.h>
140 #include "ptserver.h"
141 #include "ptprototypes.h"
142 #include "error_macros.h"
144 /* make all of these into a structure if you want */
145 struct prheader cheader
;
146 struct ubik_dbase
*dbase
;
147 struct afsconf_dir
*prdir
;
149 #if defined(SUPERGROUPS)
150 extern afs_int32 depthsg
;
154 int restrict_anonymous
= 0;
157 int rxkadDisableDotCheck
= 0;
159 #define ADDRSPERSITE 16 /* Same global is in rx/rx_user.c */
160 afs_uint32 SHostAddrs
[ADDRSPERSITE
];
162 static struct afsconf_cell info
;
164 extern int prp_group_default
;
165 extern int prp_user_default
;
167 #include "AFS_component_version_number.c"
170 prp_access_mask(char *s
)
173 if (*s
>= '0' && *s
<= '9') {
174 return strtol(s
, NULL
, 0);
177 while (*s
) switch(*s
++)
179 case 'S': r
|= PRP_STATUS_ANY
; break;
180 case 's': r
|= PRP_STATUS_MEM
; break;
181 case 'O': r
|= PRP_OWNED_ANY
; break;
182 case 'M': r
|= PRP_MEMBER_ANY
; break;
183 case 'm': r
|= PRP_MEMBER_MEM
; break;
184 case 'A': r
|= PRP_ADD_ANY
; break;
185 case 'a': r
|= PRP_ADD_MEM
; break;
186 case 'r': r
|= PRP_REMOVE_MEM
; break;
191 /* check whether caller is authorized to manage RX statistics */
193 pr_rxstat_userok(struct rx_call
*call
)
195 return afsconf_SuperUser(prdir
, call
, NULL
);
199 * Return true if this name is a member of the local realm.
202 pr_IsLocalRealmMatch(void *rock
, char *name
, char *inst
, char *cell
)
204 struct afsconf_dir
*dir
= (struct afsconf_dir
*)rock
;
205 afs_int32 islocal
= 0; /* default to no */
208 code
= afsconf_IsLocalRealmMatch(dir
, &islocal
, name
, inst
, cell
);
210 ViceLog(0, ("Failed local realm check; code=%d, name=%s, inst=%s, cell=%s\n",
211 code
, name
, inst
, cell
));
222 OPT_restrict_anonymous
,
241 main(int argc
, char **argv
)
247 struct rx_service
*tservice
;
248 struct rx_securityClass
**securityClasses
;
249 afs_int32 numClasses
;
251 char clones
[MAXHOSTSPERCELL
];
252 afs_uint32 host
= htonl(INADDR_ANY
);
253 struct cmd_syndesc
*opts
;
254 struct cmd_item
*list
;
258 struct logOptions logopts
;
259 char *whoami
= "ptserver";
261 char *auditFileName
= NULL
;
262 char *interface
= NULL
;
266 * The following signal action for AIX is necessary so that in case of a
267 * crash (i.e. core is generated) we can include the user's data section
268 * in the core dump. Unfortunately, by default, only a partial core is
269 * generated which, in many cases, isn't too useful.
271 struct sigaction nsa
;
273 sigemptyset(&nsa
.sa_mask
);
274 nsa
.sa_handler
= SIG_DFL
;
275 nsa
.sa_flags
= SA_FULLDUMP
;
276 sigaction(SIGABRT
, &nsa
, NULL
);
277 sigaction(SIGSEGV
, &nsa
, NULL
);
280 osi_audit(PTS_StartEvent
, 0, AUD_END
);
282 /* Initialize dirpaths */
283 if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK
)) {
285 ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR
, 0, argv
[0], 0);
287 fprintf(stderr
, "%s: Unable to obtain AFS server directory.\n",
292 pr_dbaseName
= strdup(AFSDIR_SERVER_PRDB_FILEPATH
);
293 configDir
= strdup(AFSDIR_SERVER_ETC_DIRPATH
);
294 memset(&logopts
, 0, sizeof(logopts
));
296 #if defined(SUPERGROUPS)
297 /* make sure the structures for database records are the same size */
298 if ((sizeof(struct prentry
) != ENTRYSIZE
)
299 || (sizeof(struct prentryg
) != ENTRYSIZE
)) {
301 "The structures for the database records are different"
302 " sizes\n" "struct prentry = %" AFS_SIZET_FMT
"\n"
303 "struct prentryg = %" AFS_SIZET_FMT
"\n"
304 "ENTRYSIZE = %d\n", sizeof(struct prentry
),
305 sizeof(struct prentryg
), ENTRYSIZE
);
310 cmd_DisableAbbreviations();
311 cmd_DisablePositionalCommands();
312 opts
= cmd_CreateSyntax(NULL
, NULL
, NULL
, 0, NULL
);
314 /* ptserver specific options */
315 cmd_AddParmAtOffset(opts
, OPT_database
, "-database", CMD_SINGLE
,
316 CMD_OPTIONAL
, "database file");
317 cmd_AddParmAlias(opts
, OPT_database
, "-db");
319 cmd_AddParmAtOffset(opts
, OPT_access
, "-default_access", CMD_LIST
,
320 CMD_OPTIONAL
, "default access flags for new entries");
321 #if defined(SUPERGROUPS)
322 cmd_AddParmAtOffset(opts
, OPT_groupdepth
, "-groupdepth", CMD_SINGLE
,
323 CMD_OPTIONAL
, "max search depth for supergroups");
324 cmd_AddParmAlias(opts
, OPT_groupdepth
, "-depth");
326 cmd_AddParmAtOffset(opts
, OPT_restricted
, "-restricted", CMD_FLAG
,
327 CMD_OPTIONAL
, "enable restricted mode");
328 cmd_AddParmAtOffset(opts
, OPT_restrict_anonymous
, "-restrict_anonymous",
329 CMD_FLAG
, CMD_OPTIONAL
, "enable restricted anonymous mode");
331 /* general server options */
332 cmd_AddParmAtOffset(opts
, OPT_auditlog
, "-auditlog", CMD_SINGLE
,
333 CMD_OPTIONAL
, "location of audit log");
334 cmd_AddParmAtOffset(opts
, OPT_auditiface
, "-audit-interface", CMD_SINGLE
,
335 CMD_OPTIONAL
, "interface to use for audit logging");
336 cmd_AddParmAtOffset(opts
, OPT_config
, "-config", CMD_SINGLE
,
337 CMD_OPTIONAL
, "configuration location");
338 cmd_AddParmAtOffset(opts
, OPT_debug
, "-d", CMD_SINGLE
,
339 CMD_OPTIONAL
, "debug level");
340 cmd_AddParmAtOffset(opts
, OPT_logfile
, "-logfile", CMD_SINGLE
,
341 CMD_OPTIONAL
, "location of logfile");
342 cmd_AddParmAtOffset(opts
, OPT_threads
, "-p", CMD_SINGLE
,
343 CMD_OPTIONAL
, "number of threads");
345 cmd_AddParmAtOffset(opts
, OPT_syslog
, "-syslog", CMD_SINGLE_OR_FLAG
,
346 CMD_OPTIONAL
, "log to syslog");
348 cmd_AddParmAtOffset(opts
, OPT_transarc_logs
, "-transarc-logs", CMD_FLAG
,
349 CMD_OPTIONAL
, "enable Transarc style logging");
352 cmd_AddParmAtOffset(opts
, OPT_peer
, "-enable_peer_stats", CMD_FLAG
,
353 CMD_OPTIONAL
, "enable RX transport statistics");
354 cmd_AddParmAtOffset(opts
, OPT_process
, "-enable_process_stats", CMD_FLAG
,
355 CMD_OPTIONAL
, "enable RX RPC statistics");
356 cmd_AddParmAtOffset(opts
, OPT_rxbind
, "-rxbind", CMD_FLAG
,
357 CMD_OPTIONAL
, "bind only to the primary interface");
358 cmd_AddParmAtOffset(opts
, OPT_rxmaxmtu
, "-rxmaxmtu", CMD_SINGLE
,
359 CMD_OPTIONAL
, "maximum MTU for RX");
362 cmd_AddParmAtOffset(opts
, OPT_dotted
, "-allow-dotted-principals",
363 CMD_FLAG
, CMD_OPTIONAL
,
364 "permit Kerberos 5 principals with dots");
366 code
= cmd_Parse(argc
, argv
, &opts
);
367 if (code
== CMD_HELP
) {
373 cmd_OptionAsString(opts
, OPT_config
, &configDir
);
375 cmd_OpenConfigFile(AFSDIR_SERVER_CONFIG_FILE_FILEPATH
);
376 cmd_SetCommandName("ptserver");
378 if (cmd_OptionAsList(opts
, OPT_access
, &list
) == 0) {
379 prp_user_default
= prp_access_mask(list
->data
);
380 if (list
->next
== NULL
|| list
->next
->data
== NULL
) {
381 fprintf(stderr
, "Missing second argument for -default_access\n");
384 prp_group_default
= prp_access_mask(list
->next
->data
);
387 #if defined(SUPERGROUPS)
388 cmd_OptionAsInt(opts
, OPT_groupdepth
, &depthsg
);
391 cmd_OptionAsFlag(opts
, OPT_restricted
, &restricted
);
392 cmd_OptionAsFlag(opts
, OPT_restrict_anonymous
, &restrict_anonymous
);
394 /* general server options */
395 cmd_OptionAsString(opts
, OPT_auditlog
, &auditFileName
);
397 if (cmd_OptionAsString(opts
, OPT_auditiface
, &interface
) == 0) {
398 if (osi_audit_interface(interface
)) {
399 printf("Invalid audit interface '%s'\n", interface
);
405 cmd_OptionAsString(opts
, OPT_database
, &pr_dbaseName
);
407 if (cmd_OptionAsInt(opts
, OPT_threads
, &lwps
) == 0) {
408 if (lwps
> 64) { /* maximum of 64 */
409 printf("Warning: '-p %d' is too big; using %d instead\n",
412 } else if (lwps
< 3) { /* minimum of 3 */
413 printf("Warning: '-p %d' is too small; using %d instead\n",
420 if (cmd_OptionPresent(opts
, OPT_syslog
)) {
421 if (cmd_OptionPresent(opts
, OPT_logfile
)) {
422 fprintf(stderr
, "Invalid options: -syslog and -logfile are exclusive.");
425 if (cmd_OptionPresent(opts
, OPT_transarc_logs
)) {
426 fprintf(stderr
, "Invalid options: -syslog and -transarc-logs are exclusive.");
429 logopts
.lopt_dest
= logDest_syslog
;
430 logopts
.lopt_facility
= LOG_DAEMON
;
431 logopts
.lopt_tag
= "ptserver";
432 cmd_OptionAsInt(opts
, OPT_syslog
, &logopts
.lopt_facility
);
436 logopts
.lopt_dest
= logDest_file
;
437 if (cmd_OptionPresent(opts
, OPT_transarc_logs
)) {
438 logopts
.lopt_rotateOnOpen
= 1;
439 logopts
.lopt_rotateStyle
= logRotate_old
;
441 if (cmd_OptionPresent(opts
, OPT_logfile
))
442 cmd_OptionAsString(opts
, OPT_logfile
, (char**)&logopts
.lopt_filename
);
444 logopts
.lopt_filename
= AFSDIR_SERVER_PTLOG_FILEPATH
;
446 cmd_OptionAsInt(opts
, OPT_debug
, &logopts
.lopt_logLevel
);
449 if (cmd_OptionPresent(opts
, OPT_peer
))
450 rx_enablePeerRPCStats();
452 if (cmd_OptionPresent(opts
, OPT_process
))
453 rx_enableProcessRPCStats();
455 cmd_OptionAsFlag(opts
, OPT_rxbind
, &rxBind
);
457 cmd_OptionAsInt(opts
, OPT_rxmaxmtu
, &rxMaxMTU
);
460 cmd_OptionAsFlag(opts
, OPT_dotted
, &rxkadDisableDotCheck
);
462 cmd_FreeOptions(&opts
);
465 osi_audit_file(auditFileName
);
466 osi_audit(PTS_StartEvent
, 0, AUD_END
);
470 #ifdef AFS_PTHREAD_ENV
472 SetupLogSoftSignals();
477 prdir
= afsconf_Open(configDir
);
479 fprintf(stderr
, "ptserver: can't open configuration directory.\n");
482 if (afsconf_GetNoAuthFlag(prdir
))
483 printf("ptserver: running unauthenticated\n");
486 /* initialize winsock */
487 if (afs_winsockInit() < 0) {
488 ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED
, 0, argv
[0], 0);
490 fprintf(stderr
, "ptserver: couldn't initialize winsock. \n");
495 gethostname(hostname
, sizeof(hostname
));
496 th
= gethostbyname(hostname
);
498 fprintf(stderr
, "ptserver: couldn't get address of this host.\n");
501 memcpy(&myHost
, th
->h_addr
, sizeof(afs_uint32
));
503 /* get list of servers */
505 afsconf_GetExtendedCellInfo(prdir
, NULL
, "afsprot", &info
, clones
);
507 afs_com_err(whoami
, code
, "Couldn't get server list");
511 /* initialize audit user check */
512 osi_audit_set_user_check(prdir
, pr_IsLocalRealmMatch
);
514 /* initialize ubik */
515 ubik_SetClientSecurityProcs(afsconf_ClientAuth
, afsconf_UpToDate
, prdir
);
516 ubik_SetServerSecurityProcs(afsconf_BuildServerSecurityObjects
,
517 afsconf_CheckAuth
, prdir
);
519 /* The max needed is when deleting an entry. A full CoEntry deletion
520 * required removal from 39 entries. Each of which may refers to the entry
521 * being deleted in one of its CoEntries. If a CoEntry is freed its
522 * predecessor CoEntry will be modified as well. Any freed blocks also
523 * modifies the database header. Counting the entry being deleted and its
524 * CoEntry this adds up to as much as 1+1+39*3 = 119. If all these entries
525 * and the header are in separate Ubik buffers then 120 buffers may be
527 ubik_nBuffers
= 120 + /*fudge */ 40;
531 if (AFSDIR_SERVER_NETRESTRICT_FILEPATH
||
532 AFSDIR_SERVER_NETINFO_FILEPATH
) {
534 ccode
= afsconf_ParseNetFiles(SHostAddrs
, NULL
, NULL
,
535 ADDRSPERSITE
, reason
,
536 AFSDIR_SERVER_NETINFO_FILEPATH
,
537 AFSDIR_SERVER_NETRESTRICT_FILEPATH
);
540 ccode
= rx_getAllAddr(SHostAddrs
, ADDRSPERSITE
);
543 host
= SHostAddrs
[0];
544 /* the following call is idempotent so if/when it gets called
545 * again by the ubik init stuff, it doesn't really matter
548 rx_InitHost(host
, htons(AFSCONF_PROTPORT
));
552 /* Disable jumbograms */
555 if (rxMaxMTU
!= -1) {
556 if (rx_SetMaxMTU(rxMaxMTU
) != 0) {
557 printf("rxMaxMTU %d is invalid\n", rxMaxMTU
);
563 ubik_ServerInitByInfo(myHost
, htons(AFSCONF_PROTPORT
), &info
, clones
,
564 pr_dbaseName
, &dbase
);
566 afs_com_err(whoami
, code
, "Ubik init failed");
570 #if defined(SUPERGROUPS)
574 afsconf_BuildServerSecurityObjects(prdir
, &securityClasses
, &numClasses
);
577 rx_NewServiceHost(host
, 0, PRSRV
, "Protection Server", securityClasses
,
578 numClasses
, PR_ExecuteRequest
);
579 if (tservice
== (struct rx_service
*)0) {
580 fprintf(stderr
, "ptserver: Could not create new rx service.\n");
583 rx_SetMinProcs(tservice
, 2);
584 rx_SetMaxProcs(tservice
, lwps
);
585 if (rxkadDisableDotCheck
) {
586 rx_SetSecurityConfiguration(tservice
, RXS_CONFIG_FLAGS
,
587 (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK
);
591 rx_NewServiceHost(host
, 0, RX_STATS_SERVICE_ID
, "rpcstats",
592 securityClasses
, numClasses
, RXSTATS_ExecuteRequest
);
593 if (tservice
== (struct rx_service
*)0) {
594 fprintf(stderr
, "ptserver: Could not create new rx service.\n");
597 rx_SetMinProcs(tservice
, 2);
598 rx_SetMaxProcs(tservice
, 4);
600 /* allow super users to manage RX statistics */
601 rx_SetRxStatUserOk(pr_rxstat_userok
);
603 LogCommandLine(argc
, argv
, "ptserver",
604 #if defined(SUPERGROUPS)
609 "Starting AFS", FSLog
);
610 if (afsconf_GetLatestKey(prdir
, NULL
, NULL
) == 0) {
615 osi_audit(PTS_FinishEvent
, -1, AUD_END
);