4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
31 #include <nss_dbdefs.h>
33 #include <auth_attr.h>
34 #include <prof_attr.h>
35 #include <user_attr.h>
37 #define COPYTOSTACK(dst, csrc) { \
38 size_t len = strlen(csrc) + 1; \
40 (void) memcpy(dst, csrc, len); \
43 static kva_t
*get_default_attrs(const char *);
44 static void free_default_attrs(kva_t
*);
47 * Enumeration functions for auths and profiles; the enumeration functions
48 * take a callback with four arguments:
49 * const char * profile name (or NULL unless wantattr is false)
50 * kva_t * attributes (or NULL unless wantattr is true)
52 * void * pointer to the result
53 * When the call back returns non-zero, the enumeration ends.
54 * The function might be NULL but only for profiles as we are always collecting
56 * Both the auths and the profiles arguments may be NULL.
58 * These should be the only implementation of the algorithm of "finding me
59 * all the profiles/athorizations/keywords/etc.
62 #define CONSUSER_PROFILE_KW "consprofile"
63 #define DEF_LOCK_AFTER_RETRIES "LOCK_AFTER_RETRIES="
65 static struct dfltplcy
{
69 /* CONSUSER MUST BE FIRST! */
70 { CONSUSER_PROFILE_KW
, DEF_CONSUSER
},
71 { PROFATTR_AUTHS_KW
, DEF_AUTH
},
72 { PROFATTR_PROFS_KW
, DEF_PROF
},
73 { USERATTR_LIMPRIV_KW
, DEF_LIMITPRIV
},
74 { USERATTR_DFLTPRIV_KW
, DEF_DFLTPRIV
},
75 { USERATTR_LOCK_AFTER_RETRIES_KW
, DEF_LOCK_AFTER_RETRIES
}
78 #define NDFLTPLY (sizeof (dfltply)/sizeof (struct dfltplcy))
79 #define GETCONSPROF(a) (kva_match((a), CONSUSER_PROFILE_KW))
80 #define GETPROF(a) (kva_match((a), PROFATTR_PROFS_KW))
83 * Enumerate profiles from listed profiles.
85 static int _auth_match_noun(const char *, const char *, size_t, const char *);
88 _enum_common_p(const char *cprofiles
,
89 int (*cb
)(const char *, kva_t
*, void *, void *),
90 void *ctxt
, void *pres
, boolean_t wantattr
,
91 int *pcnt
, char *profs
[MAXPROFS
])
99 if (cprofiles
== NULL
)
102 if (*pcnt
> 0 && strcmp(profs
[*pcnt
- 1], PROFILE_STOP
) == 0)
105 COPYTOSTACK(profiles
, cprofiles
)
107 while (prof
= strtok_r(profiles
, KV_SEPSTR
, &last
)) {
109 profiles
= NULL
; /* For next iterations of strtok_r */
111 for (i
= 0; i
< *pcnt
; i
++)
112 if (strcmp(profs
[i
], prof
) == 0)
115 if (*pcnt
>= MAXPROFS
) /* oops: too many profs */
119 profs
[(*pcnt
)++] = strdup(prof
);
121 if (strcmp(profs
[*pcnt
- 1], PROFILE_STOP
) == 0)
124 /* find the profiles for this profile */
125 pa
= getprofnam(prof
);
127 if (cb
!= NULL
&& (!wantattr
|| pa
!= NULL
&& pa
->attr
!= NULL
))
128 res
= cb(prof
, pa
? pa
->attr
: NULL
, ctxt
, pres
);
131 if (res
== 0 && pa
->attr
!= NULL
) {
132 res
= _enum_common_p(GETPROF(pa
->attr
), cb
,
133 ctxt
, pres
, wantattr
, pcnt
, profs
);
146 * Enumerate all attributes associated with a username and the profiles
147 * associated with the user.
150 _enum_common(const char *username
,
151 int (*cb
)(const char *, kva_t
*, void *, void *),
152 void *ctxt
, void *pres
, boolean_t wantattr
)
157 char *profs
[MAXPROFS
];
163 ua
= getusernam(username
);
166 if (ua
->attr
!= NULL
) {
168 res
= cb(NULL
, ua
->attr
, ctxt
, pres
);
170 res
= _enum_common_p(GETPROF(ua
->attr
),
171 cb
, ctxt
, pres
, wantattr
, &cnt
, profs
);
176 free_proflist(profs
, cnt
);
181 if ((cnt
== 0 || strcmp(profs
[cnt
-1], PROFILE_STOP
) != 0) &&
182 (kattrs
= get_default_attrs(username
)) != NULL
) {
184 res
= _enum_common_p(GETCONSPROF(kattrs
), cb
, ctxt
, pres
,
185 wantattr
, &cnt
, profs
);
188 res
= _enum_common_p(GETPROF(kattrs
), cb
, ctxt
, pres
,
189 wantattr
, &cnt
, profs
);
192 if (res
== 0 && wantattr
)
193 res
= cb(NULL
, kattrs
, ctxt
, pres
);
195 free_default_attrs(kattrs
);
198 free_proflist(profs
, cnt
);
204 * Enumerate profiles with a username argument.
207 _enum_profs(const char *username
,
208 int (*cb
)(const char *, kva_t
*, void *, void *),
209 void *ctxt
, void *pres
)
211 return (_enum_common(username
, cb
, ctxt
, pres
, B_FALSE
));
215 * Enumerate attributes with a username argument.
218 _enum_attrs(const char *username
,
219 int (*cb
)(const char *, kva_t
*, void *, void *),
220 void *ctxt
, void *pres
)
222 return (_enum_common(username
, cb
, ctxt
, pres
, B_TRUE
));
227 * Enumerate authorizations in the "auths" argument.
230 _enum_auths_a(const char *cauths
, int (*cb
)(const char *, void *, void *),
231 void *ctxt
, void *pres
)
233 char *auth
, *last
, *auths
;
236 if (cauths
== NULL
|| cb
== NULL
)
239 COPYTOSTACK(auths
, cauths
)
241 while (auth
= strtok_r(auths
, KV_SEPSTR
, &last
)) {
242 auths
= NULL
; /* For next iterations of strtok_r */
244 res
= cb(auth
, ctxt
, pres
);
253 * Magic struct and function to allow using the _enum_attrs functions to
254 * enumerate the authorizations.
256 typedef struct ccomm2auth
{
257 int (*cb
)(const char *, void *, void *);
263 comm2auth(const char *name
, kva_t
*attr
, void *ctxt
, void *pres
)
265 ccomm2auth
*ca
= ctxt
;
268 /* Note: PROFATTR_AUTHS_KW is equal to USERATTR_AUTHS_KW */
269 auths
= kva_match(attr
, PROFATTR_AUTHS_KW
);
270 return (_enum_auths_a(auths
, ca
->cb
, ca
->ctxt
, pres
));
274 * Enumerate authorizations for username.
277 _enum_auths(const char *username
,
278 int (*cb
)(const char *, void *, void *),
279 void *ctxt
, void *pres
)
289 return (_enum_common(username
, comm2auth
, &c2a
, pres
, B_TRUE
));
293 _auth_match_noun(const char *pattern
, const char *auth
,
294 size_t auth_len
, const char *auth_noun
)
301 pattern_len
= strlen(pattern
);
303 * If the specified authorization has a trailing object
304 * and the current authorization we're checking also has
305 * a trailing object, the object names must match.
307 * If there is no object name failure, then we must
308 * check for an exact match of the two authorizations
310 if (auth_noun
!= NULL
) {
311 if ((slash
= strchr(pattern
, KV_OBJECTCHAR
)) != NULL
) {
312 pattern_noun
= slash
+ 1;
313 pattern_len
-= strlen(slash
);
314 if (strcmp(pattern_noun
, auth_noun
) != 0)
316 } else if ((auth_len
== pattern_len
) &&
317 (strncmp(pattern
, auth
, pattern_len
) == 0)) {
323 * If the wildcard is not in the last position in the string, don't
326 if (pattern
[pattern_len
-1] != KV_WILDCHAR
)
330 * If the strings are identical up to the wildcard and auth does not
331 * end in "grant", then we have a match.
333 if (strncmp(pattern
, auth
, pattern_len
- 1) == 0) {
334 grant
= strrchr(auth
, '.');
336 if (strncmp(grant
+ 1, "grant", 5) != 0)
344 _auth_match(const char *pattern
, const char *auth
)
346 return (_auth_match_noun(pattern
, auth
, strlen(auth
), NULL
));
350 _is_authorized(const char *auth
, void *authname
, void *res
)
358 auth_len
= strlen(authname
);
359 if ((slash
= strchr(authname
, KV_OBJECTCHAR
)) != NULL
) {
360 authname_noun
= slash
+ 1;
361 noun_len
= strlen(slash
);
362 auth_len
-= noun_len
;
364 authname_noun
= NULL
;
367 if (strcmp(authname
, auth
) == 0) {
368 /* exact match, we're done */
371 } else if (noun_len
|| strchr(auth
, KV_WILDCHAR
) != NULL
) {
372 if (_auth_match_noun(auth
, authname
,
373 auth_len
, authname_noun
)) {
383 chkauthattr(const char *authname
, const char *username
)
385 int auth_granted
= 0;
387 if (authname
== NULL
|| username
== NULL
)
390 (void) _enum_auths(username
, _is_authorized
, (char *)authname
,
393 return (auth_granted
);
396 #define CONSOLE_USER_LINK "/dev/vt/console_user"
399 is_cons_user(const char *user
)
403 char pwbuf
[NSS_BUFLEN_PASSWD
];
404 struct passwd
*result
;
409 if (stat(CONSOLE_USER_LINK
, &cons
) == -1) {
412 getpwnam_r(user
, &pw
, pwbuf
, sizeof (pwbuf
), &result
);
417 return (pw
.pw_uid
== cons
.st_uid
);
421 free_default_attrs(kva_t
*kva
)
425 for (i
= 0; i
< kva
->length
; i
++)
426 free(kva
->data
[i
].value
);
432 * Return the default attributes; this are ignored when a STOP profile
436 get_default_attrs(const char *user
)
442 kva
= malloc(sizeof (kva_t
) + sizeof (kv_t
) * NDFLTPLY
);
447 kva
->data
= (kv_t
*)(void *)&kva
[1];
450 if ((defp
= defopen_r(AUTH_POLICY
)) == NULL
)
453 for (i
= is_cons_user(user
) ? 0 : 1; i
< NDFLTPLY
; i
++) {
454 char *cp
= defread_r(dfltply
[i
].defkw
, defp
);
458 if ((cp
= strdup(cp
)) == NULL
)
461 kva
->data
[kva
->length
].key
= dfltply
[i
].attr
;
462 kva
->data
[kva
->length
++].value
= cp
;
465 (void) defclose_r(defp
);
470 (void) defclose_r(defp
);
472 free_default_attrs(kva
);