subsys.c example
The subsys.c program is similar to
auths(C),
but it lists a user's subsystem
authorizations rather than kernel authorizations.
The subsys command takes one argument, a user name.
If no name is specified,
subsys works on the effective user ID.
It prints out the name of the account,
the real name of the person assigned to the account,
and the subsystem authorizations
(both primary and secondary) for that account.
This program can be run only by the owner of the account
or the accounts administrator
(in other words, a user with the auth subsystem authorization).
This program demonstrates how to:
Any program that queries the Protected Password database
must be executed with the effective group ID
(EUID) of auth.
To install this program, make the binary
setgid auth. For example, use
the following commands:
chgrp auth subsys
chmod 2111 subsys
To compile this program, use the following command:
cc subsys.c -lprot -lx -o subsys
subsys.c (Part 1/2)
1 #define SecureWare /* enable security features */
2 #include <sys/types.h> /* system pseudo-types */
3 #include <stdio.h> /* standard I/O definitions */
4 #include <pwd.h> /* /etc/passwd definitions */
5 #include <string.h> /* string library definitions */
6 #include <sys/security.h> /* various security definitions */
7 #include <sys/audit.h> /* audit definitions */
8 #include <prot.h> /* database definitions */
9 main(
10 int argc,
11 char *argv[]
12 ) {
13 struct pr_passwd *pr; /* Protected Password entry */
14 struct passwd *pwd; /* /etc/passwd entry */
15 mask_t *pmask; /* subsys authorization vector */
16 char *str;
17 int n, num;
18 int printed;
19 set_auth_parameters(argc, argv);
20 if (argc >= 2)
21 pwd = getpwnam(argv[1]);
22 else
23 pwd = getpwuid(starting_euid());
24 if (pwd == (struct passwd *)0) {
25 (void) fprintf(stderr, "%s: No such user.\n", command_name);
26 exit(2);
27 /* NOTREACHED */
28 }
29 if (pwd->pw_uid != starting_luid() && ! authorized_user("auth")) {
30 (void) fprintf(stderr, "%s: Not authorized.\n", command_name);
31 exit(3);
32 /* NOTREACHED */
33 }
line 1-
SecureWare must be defined in programs
that use the trusted software. If it is not defined on the compile line,
the
#define SecureWare
statement is required.
This allows the security-related definitions in the
header files to be interpreted correctly.
line 4-
pwd.h defines the passwd structure.
Trusted software uses this information
to identify the user, as in line 24.
This file must be included to use such routines as
getpwnam(S)
(line 21) and
getpwuid(S)
(line 23).
line 5-
string.h is required for the
strchr(S)
call in line 35.
The manual page for each routine
defines which
#include
lines
are required when calling that routine.
lines 6-8-
These lines contain header files that define
the trusted software.
line 19-
This line initializes the authentication routines.
This must be the first action in main().
The two arguments, count
and vector, call the program.
The
identity(S)
manual page describes
set_auth_parameters().
lines 20-28-
These lines get the /etc/passwd entry
for the account named on the command line.
If no name is specified, use the current
EUID
(Effective User Identification).
If there is no entry in /etc/passwd
(in other words, the account does not exist),
then exit with an error message.
Note that it is not a security relevant event
when the program
reports that an account does not exist, because
you can determine this
by looking at the /etc/passwd file
which can be read by all users.
lines 29-33-
These lines check that the user is permitted to see the
authorizations for the account.
Only the account owner
(the
UID
matches the
LUID)
or the accounts administrator
(a user who has auth subsystem authorization)
can check the authorizations for the account.
An unauthorized user does not need
to know the authorizations of another user.
subsys.c (Part 2/2)
34 (void) printf("User name: %s\n", pwd->pw_name);
35 if ((str = strchr(pwd->pw_gecos, ',')) != (char *)0)
36 *str = '\0';
37 (void) printf("Real name: %s\n", pwd->pw_gecos);
38 (void) printf("Subsystems:");
39 pmask = (mask_t *)0;
40 if ((pr = getprpwnam(pwd->pw_name)) == (struct pr_passwd *)0) {
41 audit_auth_entry(pwd->pw_name, OT_PRPWD,
42 "User missing from Protected Password database"
43 );
44 str = "UNKNOWN (no Protected Password entry)";
45 }
46 else if (build_cmd_priv() || (num = total_auths()) < 0) {
47 audit_security_failure(
48 OT_SUBSYS, 1L, 0L, "Subsystem names", "Not listed"
49 );
50 str = "UNKNOWN (cannot build list of subsystem names)";
51 }
52 else if (pr->uflg.fg_cprivs)
53 pmask = pr->ufld.fd_cprivs;
54 else if (pr->sflg.fg_cprivs)
55 pmask = pr->sfld.fd_cprivs;
56 else
57 str = "NONE";
58 printed=0;
59 if (pmask == (mask_t *)0)
60 (void) printf(" %s", str);
61 else {
62 for (n = 0; n < num; n++)
63 if (ISBITSET(pmask, cmd_priv[n].value)) {
64 printed=1;
65 (void) printf(" %s", cmd_priv[n].name);
66 }
67 }
68 if(!printed)
69 (void) printf ("NONE");
70 putchar('\n');
71 (void) fflush(stdout);
72 exit(ferror(stdout));
73 /* NOTREACHED */
74 }
lines 34-38-
These lines report the name of the account and the person's real name
(which is assumed to be the part of the
pw_gecos
field
in the /etc/passwd file
that precedes the first comma).
lines 39-45-
These lines get the subsystem authorization vector for the account.
Because the account exists in the /etc/passwd file,
it must have a Protected Password entry.
If it does not, it is an auditable problem.
(Note that this may not be true if the account is
defined via client-mode NIS, but it will
be hidden from the calling program.)
lines 41-43-
The
audit_auth_entry(S)
call produces this type of an audit record.
The first argument is the name of the user from the
/etc/passwd file;
the second argument identifies the type of problem
(OT_PRPWD is the Protected Password database;
see the audit.h header file
for a list of valid type flags);
the third argument is a literal string
that is recorded in the audit database.
See
authaudit(S)
for a list of routines that record other types of audit records.
lines 46-51-
These lines obtain the names of the installed subsystems;
if none are listed,
audit the failure.
lines 47-49-
The first argument to audit_security_failure
defines the object in which the problem was detected;
OT_SUBSYS indicates the Subsystem database.
See the audit.h header file for a list of valid values.
The second and third arguments record the expected
and current values to help in diagnosing the problem;
the fourth and fifth arguments identify
additional information about the problem.
In these sample programs,
the messages are hard-coded in English.
If you anticipate needing to localize your application, implement
these messages (lines 47-51) using a message catalog
so the messages print in the chosen language
of the user.
lines 52-58-
If the fg_cprivs flag is set in the pr_passwd structure,
the account has a private list of subsystem authorizations.
If not, the system default applies.
If the system default list does not exist,
there are no default authorizations; in this
specific case, this is not
considered an error. However,
in most cases, this would be considered an error
that should be audited.
If there are no default authorizations,
assign a restrictive value for the authorizations.
lines 59-70-
These lines list the subsystem authorizations for the account.
Next topic:
prwarn.c example
Previous topic:
Programming examples
© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003