5 * pt_util: Program to dump the AFS protection server database
8 * Assumptions: We *cheat* here and read the datafile directly, ie.
9 * not going through the ubik distributed data manager.
10 * therefore the database must be quiescent for the
11 * output of this program to be valid.
14 #include <afsconfig.h>
15 #include <afs/param.h>
22 #define L_SET SEEK_SET
26 #include <afs/com_err.h>
27 #include <afs/cmd.h> /*Command line parsing */
28 #include <afs/afsutil.h>
30 #define UBIK_INTERNALS
38 #include "ptprototypes.h"
40 #define IDHash(x) (abs(x) % HASHSIZE)
41 #define print_id(x) ( ((flags&DO_SYS)==0 && (x<-32767 || x>97536)) || \
42 ((flags&DO_OTR)==0 && (x>-32768 && x<97537)))
51 static int display_entry(int);
52 static void add_group(long);
53 static void display_groups(void);
54 static void display_group(int);
55 static void fix_pre(struct prentry
*);
56 static char *id_to_name(int);
57 static char *checkin(struct prentry
*);
58 static char *check_core(int);
59 static int CommandProc(struct cmd_syndesc
*, void *);
62 char h_name
[PR_MAXNAMELEN
];
64 struct hash_entry
*next
;
66 struct hash_entry
*hat
[HASHSIZE
];
68 static struct contentry prco
;
69 static struct prentry pre
;
70 static struct prheader prh
;
71 static struct ubik_version uv
;
74 struct grp_list
*next
;
77 static struct grp_list
*grp_head
= 0;
78 static long grp_count
= 0;
81 struct usr_list
*next
;
82 char name
[PR_MAXNAMELEN
];
85 static struct usr_list
*usr_head
= 0;
91 #define FMT_BASE "%-10s %d/%d %d %d %d\n"
92 #define FMT_MEM " %-8s %d\n"
105 main(int argc
, char **argv
)
108 struct cmd_syndesc
*cs
; /*Command line syntax descriptor */
109 afs_int32 code
; /*Return code */
111 cs
= cmd_CreateSyntax(NULL
, CommandProc
, NULL
, 0,
112 "access protection database");
113 cmd_AddParm(cs
, "-w", CMD_FLAG
, CMD_OPTIONAL
,
114 "update prdb with contents of data file");
115 cmd_AddParm(cs
, "-user", CMD_FLAG
, CMD_OPTIONAL
, "display users");
116 cmd_AddParm(cs
, "-group", CMD_FLAG
, CMD_OPTIONAL
, "display groups");
117 cmd_AddParm(cs
, "-members", CMD_FLAG
, CMD_OPTIONAL
,
118 "display group members");
119 cmd_AddParm(cs
, "-name", CMD_FLAG
, CMD_OPTIONAL
,
120 "follow name hash chains (not id hashes)");
121 cmd_AddParm(cs
, "-system", CMD_FLAG
, CMD_OPTIONAL
,
122 "display only system data");
123 cmd_AddParm(cs
, "-xtra", CMD_FLAG
, CMD_OPTIONAL
,
124 "display extra users/groups");
125 cmd_AddParm(cs
, "-prdb", CMD_SINGLE
, CMD_OPTIONAL
, "prdb file");
126 cmd_AddParm(cs
, "-datafile", CMD_SINGLE
, CMD_OPTIONAL
, "data file");
127 code
= cmd_Dispatch(argc
, argv
);
134 CommandProc(struct cmd_syndesc
*a_as
, void *arock
)
140 struct prentry uentry
, gentry
;
143 const char *pbase
= AFSDIR_SERVER_PRDB_FILEPATH
;
146 struct cmd_parmdesc
*tparm
;
150 if (tparm
[0].items
) {
152 /* so we are treated as admin and can create "mis"owned
156 if (tparm
[1].items
) {
159 if (tparm
[2].items
) {
162 if (tparm
[3].items
) {
163 flags
|= (DO_GRP
| DO_MEM
);
165 if (tparm
[4].items
) {
168 if (tparm
[5].items
) {
171 if (tparm
[6].items
) {
174 if (tparm
[7].items
) {
175 pfile
= tparm
[7].items
->data
;
177 if (tparm
[8].items
) {
178 dfile
= tparm
[8].items
->data
;
182 snprintf(pbuffer
, sizeof(pbuffer
), "%s.DB0", pbase
);
185 if ((dbase_fd
= open(pfile
, (wflag
? O_RDWR
: O_RDONLY
) | O_CREAT
, 0600))
187 fprintf(stderr
, "pt_util: cannot open %s: %s\n", pfile
,
191 if (read(dbase_fd
, buffer
, HDRSIZE
) < 0) {
192 fprintf(stderr
, "pt_util: error reading %s: %s\n", pfile
,
198 if ((dfp
= fopen(dfile
, wflag
? "r" : "w")) == 0) {
199 fprintf(stderr
, "pt_util: error opening %s: %s\n", dfile
,
204 dfp
= (wflag
? stdin
: stdout
);
206 uh
= (struct ubik_hdr
*)buffer
;
207 if (ntohl(uh
->magic
) != UBIK_MAGIC
)
208 fprintf(stderr
, "pt_util: %s: Bad UBIK_MAGIC. Is %x should be %x\n",
209 pfile
, ntohl(uh
->magic
), UBIK_MAGIC
);
210 memcpy(&uv
, &uh
->version
, sizeof(struct ubik_version
));
212 if (wflag
&& ntohl(uv
.epoch
) == 0 && ntohl(uv
.counter
) == 0) {
213 uv
.epoch
= htonl(2); /* a ubik version of 0 or 1 has special meaning */
214 memcpy(&uh
->version
, &uv
, sizeof(struct ubik_version
));
215 lseek(dbase_fd
, 0, SEEK_SET
);
216 if (write(dbase_fd
, buffer
, HDRSIZE
) < 0) {
217 fprintf(stderr
, "pt_util: error writing ubik version to %s: %s\n",
218 pfile
, strerror(errno
));
223 /* Now that any writeback is done, swap these */
224 uv
.epoch
= ntohl(uv
.epoch
);
225 uv
.counter
= ntohl(uv
.counter
);
227 fprintf(stderr
, "Ubik Version is: %d.%d\n", uv
.epoch
, uv
.counter
);
228 if (read(dbase_fd
, &prh
, sizeof(struct prheader
)) < 0) {
229 fprintf(stderr
, "pt_util: error reading %s: %s\n", pfile
,
235 initialize_PT_error_table();
239 int seenGroup
= 0, id
= 0, flags
= 0;
241 while (fgets(buffer
, sizeof(buffer
), dfp
)) {
242 int oid
, cid
, quota
, uid
;
243 char name
[PR_MAXNAMELEN
], mem
[PR_MAXNAMELEN
];
245 if (isspace(*buffer
)) {
246 code
= sscanf(buffer
, "%s %d", mem
, &uid
);
249 "Insuffient data provided for group membership\n");
255 "Group member %s listed outside of group\n",
260 for (u
= usr_head
; u
; u
= u
->next
)
261 if (u
->uid
&& u
->uid
== uid
)
264 /* Add user - deferred because it is probably foreign */
266 if (FindByID(0, uid
))
270 && (flags
& (PRGRP
| PRQUOTA
)) ==
273 code
= pr_WriteEntry(0, 0, gpos
, &gentry
);
276 "Error setting group count on %s: %s\n",
277 name
, afs_error_message(code
));
279 code
= CreateEntry(0, u
->name
, &uid
, 1 /*idflag */ ,
281 SYSADMINID
/*oid */ ,
282 SYSADMINID
/*cid */ );
285 fprintf(stderr
, "Error while creating %s: %s\n",
286 u
->name
, afs_error_message(code
));
289 /* Add user to group */
290 if (id
== ANYUSERID
|| id
== AUTHUSERID
|| uid
== ANONYMOUSID
) {
292 } else if ((upos
= FindByID(0, uid
))
293 && (gpos
= FindByID(0, id
))) {
294 code
= pr_ReadEntry(0, 0, upos
, &uentry
);
296 code
= pr_ReadEntry(0, 0, gpos
, &gentry
);
298 code
= AddToEntry(0, &gentry
, gpos
, uid
);
300 code
= AddToEntry(0, &uentry
, upos
, id
);
305 fprintf(stderr
, "Error while adding %s to %s: %s\n", mem
,
306 name
, afs_error_message(code
));
308 code
= sscanf(buffer
, "%s %d/%d %d %d %d", name
, &flags
, "a
, &id
,
312 "Insufficient data provided for user/group\n");
321 code
= CreateEntry(0, name
, &id
, 1 /*idflag */ ,
322 flags
& PRGRP
, oid
, cid
);
323 if (code
== PRBADNAM
) {
324 u
= malloc(sizeof(struct usr_list
));
327 strcpy(u
->name
, name
);
330 fprintf(stderr
, "Error while creating %s: %s\n", name
,
331 afs_error_message(code
));
332 } else if ((flags
& PRACCESS
)
333 || (flags
& (PRGRP
| PRQUOTA
)) ==
335 gpos
= FindByID(0, id
);
336 code
= pr_ReadEntry(0, 0, gpos
, &gentry
);
338 gentry
.flags
= flags
;
339 gentry
.ngroups
= quota
;
340 code
= pr_WriteEntry(0, 0, gpos
, &gentry
);
344 "Error while setting flags on %s: %s\n", name
,
345 afs_error_message(code
));
349 for (u
= usr_head
; u
; u
= u
->next
)
351 fprintf(stderr
, "Error while creating %s: %s\n", u
->name
,
352 afs_error_message(PRBADNAM
));
354 for (i
= 0; i
< HASHSIZE
; i
++) {
355 upos
= nflag
? ntohl(prh
.nameHash
[i
]) : ntohl(prh
.idHash
[i
]);
358 newpos
= display_entry(upos
);
359 if (newpos
== upos
) {
360 fprintf(stderr
, "pt_util: hash error in %s chain %d\n",
361 nflag
? "name":"id", i
);
371 lseek(dbase_fd
, 0, L_SET
); /* rewind to beginning of file */
372 if (read(dbase_fd
, buffer
, HDRSIZE
) < 0) {
373 fprintf(stderr
, "pt_util: error reading %s: %s\n", pfile
,
377 uh
= (struct ubik_hdr
*)buffer
;
379 uh
->version
.epoch
= ntohl(uh
->version
.epoch
);
380 uh
->version
.counter
= ntohl(uh
->version
.counter
);
382 if ((uh
->version
.epoch
!= uv
.epoch
)
383 || (uh
->version
.counter
!= uv
.counter
)) {
385 "pt_util: Ubik Version number changed during execution.\n");
386 fprintf(stderr
, "Old Version = %d.%d, new version = %d.%d\n",
387 uv
.epoch
, uv
.counter
, uh
->version
.epoch
, uh
->version
.counter
);
394 display_entry(int offset
)
396 lseek(dbase_fd
, offset
+ HDRSIZE
, L_SET
);
397 if (read(dbase_fd
, &pre
, sizeof(struct prentry
)) < 0) {
398 fprintf(stderr
, "pt_util: error reading entry %d: %s\n",
399 offset
, strerror(errno
));
405 if ((pre
.flags
& PRFREE
) == 0) {
406 if (pre
.flags
& PRGRP
) {
410 if (print_id(pre
.id
) && (flags
& DO_USR
))
411 fprintf(dfp
, FMT_BASE
, pre
.name
, pre
.flags
, pre
.ngroups
,
412 pre
.id
, pre
.owner
, pre
.creator
);
416 return (nflag
? pre
.nextName
: pre
.nextID
);
425 i
= grp_count
++ % 1024;
427 g
= malloc(sizeof(struct grp_list
));
442 while (grp_count
--) {
443 i
= grp_count
% 1024;
455 display_group(int id
)
460 offset
= ntohl(prh
.idHash
[IDHash(id
)]);
462 lseek(dbase_fd
, offset
+ HDRSIZE
, L_SET
);
463 if (read(dbase_fd
, &pre
, sizeof(struct prentry
)) < 0) {
464 fprintf(stderr
, "pt_util: read i/o error: %s\n", strerror(errno
));
474 fprintf(dfp
, FMT_BASE
, pre
.name
, pre
.flags
, pre
.ngroups
, pre
.id
,
475 pre
.owner
, pre
.creator
);
479 if ((flags
& DO_MEM
) == 0)
482 for (i
= 0; i
< PRSIZE
; i
++) {
483 if ((id
= pre
.entries
[i
]) == 0)
487 if (print_id(id
) || print_grp
== 1) {
488 if (print_grp
== 0) {
489 fprintf(dfp
, FMT_BASE
, pre
.name
, pre
.flags
, pre
.ngroups
,
490 pre
.id
, pre
.owner
, pre
.creator
);
493 fprintf(dfp
, FMT_MEM
, id_to_name(id
), id
);
499 lseek(dbase_fd
, offset
+ HDRSIZE
, L_SET
);
500 if (read(dbase_fd
, &prco
, sizeof(struct contentry
)) < 0) {
501 fprintf(stderr
, "pt_util: read i/o error: %s\n",
505 prco
.next
= ntohl(prco
.next
);
506 for (i
= 0; i
< COSIZE
; i
++) {
507 prco
.entries
[i
] = ntohl(prco
.entries
[i
]);
508 if ((id
= prco
.entries
[i
]) == 0)
512 if (print_id(id
) || print_grp
== 1) {
513 if (print_grp
== 0) {
514 fprintf(dfp
, FMT_BASE
, pre
.name
, pre
.flags
,
515 pre
.ngroups
, pre
.id
, pre
.owner
, pre
.creator
);
518 fprintf(dfp
, FMT_MEM
, id_to_name(id
), id
);
521 if ((i
== COSIZE
) && prco
.next
)
530 fix_pre(struct prentry
*pre
)
534 pre
->flags
= ntohl(pre
->flags
);
535 pre
->id
= ntohl(pre
->id
);
536 pre
->cellid
= ntohl(pre
->cellid
);
537 pre
->next
= ntohl(pre
->next
);
538 pre
->nextID
= ntohl(pre
->nextID
);
539 pre
->nextName
= ntohl(pre
->nextName
);
540 pre
->owner
= ntohl(pre
->owner
);
541 pre
->creator
= ntohl(pre
->creator
);
542 pre
->ngroups
= ntohl(pre
->ngroups
);
543 pre
->nusers
= ntohl(pre
->nusers
);
544 pre
->count
= ntohl(pre
->count
);
545 pre
->instance
= ntohl(pre
->instance
);
546 pre
->owned
= ntohl(pre
->owned
);
547 pre
->nextOwned
= ntohl(pre
->nextOwned
);
548 pre
->parent
= ntohl(pre
->parent
);
549 pre
->sibling
= ntohl(pre
->sibling
);
550 pre
->child
= ntohl(pre
->child
);
551 for (i
= 0; i
< PRSIZE
; i
++) {
552 pre
->entries
[i
] = ntohl(pre
->entries
[i
]);
560 static struct prentry pre
;
563 name
= check_core(id
);
566 offset
= ntohl(prh
.idHash
[IDHash(id
)]);
568 lseek(dbase_fd
, offset
+ HDRSIZE
, L_SET
);
569 if (read(dbase_fd
, &pre
, sizeof(struct prentry
)) < 0) {
570 fprintf(stderr
, "pt_util: read i/o error: %s\n", strerror(errno
));
573 pre
.id
= ntohl(pre
.id
);
575 name
= checkin(&pre
);
578 offset
= ntohl(pre
.nextID
);
584 checkin(struct prentry
*pre
)
586 struct hash_entry
*he
, *last
;
590 last
= (struct hash_entry
*)0;
591 he
= hat
[IDHash(id
)];
598 he
= malloc(sizeof(struct hash_entry
));
600 fprintf(stderr
, "pt_util: No Memory for internal hash table.\n");
604 he
->next
= (struct hash_entry
*)0;
605 strncpy(he
->h_name
, pre
->name
, PR_MAXNAMELEN
);
606 if (last
== (struct hash_entry
*)0)
607 hat
[IDHash(id
)] = he
;
616 struct hash_entry
*he
;
617 he
= hat
[IDHash(id
)];