2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: access.c /main/5 1996/10/08 16:41:05 barstow $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company
26 * (c) Copyright 1993, 1994 International Business Machines Corp.
27 * (c) Copyright 1993, 1994 Novell, Inc.
28 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
32 #include <EUSCompat.h>
38 #include <sys/systeminfo.h>
47 #define NUM_CACHE 50 /* cache for unix user name */
51 typedef struct uname_cache {
52 uid_t uid; /* unix user id */
53 char *name; /* user name */
54 struct uname_cache *next;
57 static Uname_cache *ucache_list = NULL;
59 /******************************************************************************
60 * forward declaration of static functions used within the file
61 ******************************************************************************/
62 static Uname_cache * in_u_cache(uid_t uid);
63 static char * get_uname(uid_t uid);
64 static Access_Entry_4 * in_access_list(Access_Entry_4 *l, char *s);
65 static Access_Entry_4 * combine_access_list(Access_Entry_4 *p_list,
66 Access_Entry_4 *p_head, int type, int *p_world);
67 static CSA_return_code _GetV4AccessRights(_DtCmsCalendar *cal, char *target,
68 char *sender, uint *access);
69 static CSA_return_code _GetV5AccessRights(_DtCmsCalendar *cal, char *target,
70 char *sender, uint *access);
72 /*****************************************************************************
73 * extern functions used in the library
74 *****************************************************************************/
77 * If the requester is the owner, "*sender" will be set to NULL.
79 extern CSA_return_code
80 _DtCmsV4LoadAndCheckAccess(
81 struct svc_req *svcrq,
89 if (target == NULL || sender == NULL || cal == NULL)
90 return (CSA_E_INVALID_PARAMETER);
92 if ((stat = _DtCmsGetClientInfo(svcrq, sender)) != CSA_SUCCESS)
95 if ((stat = _DtCmsGetCalendarByName(target, B_TRUE, cal))
99 if ((*cal)->fversion == _DtCMS_VERSION1)
100 return (_GetV4AccessRights(*cal, target, *sender, access));
102 return (_GetV5AccessRights(*cal, target, *sender, access));
107 * If the requester is the owner, "*p_src" will be set to NULL.
109 extern CSA_return_code
110 _DtCmsV5LoadAndCheckAccess(
111 struct svc_req *svcrq,
115 _DtCmsCalendar **cal)
117 CSA_return_code stat;
118 cms_access_entry *alist;
119 cms_attribute_value *owner;
120 int worldaccess = 0, useraccess = 0;
124 if (target == NULL || sender == NULL || cal == NULL)
125 return (CSA_E_INVALID_PARAMETER);
127 if ((stat = _DtCmsGetClientInfo(svcrq, sender)) != CSA_SUCCESS)
130 if ((stat = _DtCmsGetCalendarByName(target, B_TRUE, cal))
134 if ((*cal)->fversion == _DtCMS_VERSION1)
135 return (_GetV4AccessRights(*cal, target, *sender, access));
137 return (_GetV5AccessRights(*cal, target, *sender, access));
140 extern CSA_return_code
141 _DtCmsGetClientInfo(struct svc_req *svcrq, char **source)
145 struct authunix_parms *unix_cred;
149 return (CSA_E_INVALID_PARAMETER);
152 switch (svcrq->rq_cred.oa_flavor) {
154 unix_cred = (struct authunix_parms *) svcrq->rq_clntcred;
155 if (unix_cred == NULL)
156 return (CSA_E_NO_AUTHORITY);
157 if ((name = get_uname (unix_cred->aup_uid)) == NULL)
158 return (CSA_E_INSUFFICIENT_MEMORY);
159 if ((uname = malloc(strlen(name) +
160 strlen(unix_cred->aup_machname) + 2)) == NULL)
161 return (CSA_E_INSUFFICIENT_MEMORY);
163 sprintf(uname, "%s@%s", name, unix_cred->aup_machname);
165 return (CSA_SUCCESS);
170 svcerr_weakauth(svcrq->rq_xprt);
171 return (CSA_E_NO_AUTHORITY);
176 * good format of owner and user assumed:
177 * owner: user[@host[.domain]]
178 * user: user@host[.domain]
179 * target: name@host[.domain]
182 _DtCmsIsFileOwner(char *owner, char *user, char *target)
184 char *ptr1, *ptr2, *ptr3;
187 fprintf(stderr, "rpc.cmsd: %s, %s = %s, %s = %s, %s = %s\n",
189 "owner", ((owner == NULL) ? "NULL" : owner),
190 "user", ((user == NULL) ? "NULL" : user),
191 "target", ((target == NULL) ? "NULL" : target));
194 if (owner == NULL || user == NULL || target == NULL)
197 ptr1 = _DtCmGetPrefix(owner, '@');
198 ptr2 = _DtCmGetPrefix(user, '@');
199 if (strcmp(ptr1, ptr2)) {
207 /* check domain if domain info is available */
209 ptr1 = strchr(user, '.');
210 ptr2 = strchr(target, '@');
212 ptr3 = strchr(ptr2, '.');
216 if (ptr1 == NULL || ptr3 == NULL)
217 /* assume that user is in the local domain */
220 return(_DtCmIsSamePath(++ptr1, ++ptr3));
224 _DtCmsShowAccessList(Access_Entry_4 *l)
227 fprintf(stderr, "Access: %s(%c%c%c)\n", l->who,
228 l->access_type & access_read_4 ? 'r' : '_',
229 l->access_type & access_write_4 ? 'w' : '_',
230 l->access_type & access_delete_4 ? 'd' : '_');
235 extern Access_Entry_4 *
236 _DtCmsCalendarAccessList(_DtCmsCalendar *cal)
238 int world = access_none_4;
240 Access_Entry_4 *l = NULL;
242 l = combine_access_list(GET_R_ACCESS(cal), l, access_read_4, &world);
243 l = combine_access_list(GET_W_ACCESS(cal), l, access_write_4, &world);
244 l = combine_access_list(GET_D_ACCESS(cal), l, access_delete_4, &world);
245 l = combine_access_list(GET_X_ACCESS(cal), l, access_exec_4, &world);
247 /* WORLD exists in one of the lists, add her to the combined list. */
248 if (world != access_none_4)
250 a = _DtCm_make_access_entry4(WORLD, world);
257 extern Privacy_Level_4
258 _DtCmCheckPrivacyLevel(char **p_src, Appt_4 *p_appt)
263 if (p_appt != NULL) {
265 * if p_src is the author of the appointment,
266 * it should see everything.
268 if (_DtCmIsSameUser(*p_src, p_appt->author)) {
272 return(p_appt->privacy);
278 * the user can view the entry if it has OWNER rights,
279 * the appropriate VIEW rights or he is the organizer of
280 * the entry and has ORGANIZER rights.
282 extern CSA_return_code
283 _DtCmsCheckViewAccess(char *user, uint access, cms_entry *eptr)
286 cms_attribute_value *oval, *sval;
288 need = (_DtCmsClassToViewAccess(eptr)) | CSA_OWNER_RIGHTS;
290 return (CSA_SUCCESS);
292 oval = eptr->attrs[CSA_ENTRY_ATTR_ORGANIZER_I].value;
293 sval = eptr->attrs[CSA_ENTRY_ATTR_SPONSOR_I].value;
294 if (((access & CSA_ORGANIZER_RIGHTS) &&
295 _DtCmIsSameUser(user, oval->item.calendar_user_value)) ||
296 ((access & CSA_SPONSOR_RIGHTS) && sval &&
297 _DtCmIsSameUser(user, sval->item.calendar_user_value)))
298 return (CSA_SUCCESS);
299 else if ( (need & ~CSA_OWNER_RIGHTS) == (CSA_VIEW_CONFIDENTIAL_ENTRIES) ) {
300 return (CSA_E_TIME_ONLY);
302 return (CSA_E_NO_AUTHORITY);
306 extern CSA_return_code
307 _DtCmsCheckChangeAccess(char *user, uint access, cms_entry *eptr)
310 cms_attribute_value *oval, *sval;
312 need = (_DtCmsClassToChangeAccess(eptr)) | CSA_OWNER_RIGHTS;
315 return (CSA_SUCCESS);
317 oval = eptr->attrs[CSA_ENTRY_ATTR_ORGANIZER_I].value;
318 sval = eptr->attrs[CSA_ENTRY_ATTR_SPONSOR_I].value;
319 if (((access & CSA_ORGANIZER_RIGHTS) &&
320 _DtCmIsSameUser(user, oval->item.calendar_user_value)) ||
321 ((access & CSA_SPONSOR_RIGHTS) && sval &&
322 _DtCmIsSameUser(user, sval->item.calendar_user_value)))
323 return (CSA_SUCCESS);
325 return (CSA_E_NO_AUTHORITY);
330 _DtCmsClassToViewAccess(cms_entry *entry)
332 cms_attribute_value *val;
334 val = entry->attrs[CSA_ENTRY_ATTR_CLASSIFICATION_I].value;
336 switch (val->item.uint32_value) {
337 case CSA_CLASS_PUBLIC:
338 return (CSA_VIEW_PUBLIC_ENTRIES);
339 case CSA_CLASS_PRIVATE:
340 return (CSA_VIEW_PRIVATE_ENTRIES);
341 case CSA_CLASS_CONFIDENTIAL:
342 return (CSA_VIEW_CONFIDENTIAL_ENTRIES);
345 fprintf(stderr, "_DtCmsClassToInsertAccess: Unsupported Class %u\n", val->item.uint32_value);
350 _DtCmsClassToInsertAccess(cms_entry *entry)
352 cms_attribute_value *val;
354 val = entry->attrs[CSA_ENTRY_ATTR_CLASSIFICATION_I].value;
356 switch (val->item.uint32_value) {
357 case CSA_CLASS_PUBLIC:
358 return (CSA_INSERT_PUBLIC_ENTRIES);
359 case CSA_CLASS_PRIVATE:
360 return (CSA_INSERT_PRIVATE_ENTRIES);
361 case CSA_CLASS_CONFIDENTIAL:
362 return (CSA_INSERT_CONFIDENTIAL_ENTRIES);
367 _DtCmsClassToChangeAccess(cms_entry *entry)
369 cms_attribute_value *val;
371 val = entry->attrs[CSA_ENTRY_ATTR_CLASSIFICATION_I].value;
373 switch (val->item.uint32_value) {
374 case CSA_CLASS_PUBLIC:
375 return (CSA_CHANGE_PUBLIC_ENTRIES);
376 case CSA_CLASS_PRIVATE:
377 return (CSA_CHANGE_PRIVATE_ENTRIES);
378 case CSA_CLASS_CONFIDENTIAL:
379 return (CSA_CHANGE_CONFIDENTIAL_ENTRIES);
383 /*****************************************************************************
384 * static functions used within the file
385 *****************************************************************************/
388 in_u_cache(uid_t uid)
390 int cache = NUM_CACHE;
392 Uname_cache *p_cache;
395 p_cache = ucache_list;
396 while (p_cache != NULL)
398 if (p_cache->uid == uid)
402 /* Assume that the cache size is at least 1 */
403 p_prev->next = p_cache->next;
404 free (p_cache->name);
406 p_cache = p_prev->next;
411 p_cache = p_cache->next;
422 Uname_cache *ucache, *prev;
424 if ((ucache = in_u_cache(uid)) == NULL)
426 if ((pw = getpwuid (uid)) == NULL) {
427 /* Can't map uid to name. Don't cache the uid. */
428 sprintf (buff, "%ld", (long)uid);
429 return (strdup(buff));
432 if ((ucache = (Uname_cache *)malloc(sizeof(Uname_cache)))
436 if ((ucache->name = strdup(pw->pw_name)) == NULL) {
441 ucache->next = ucache_list;
442 ucache_list = ucache;
445 return (strdup(ucache->name));
448 static Access_Entry_4 *
449 in_access_list(Access_Entry_4 *l, char *s)
453 if (l==NULL || s==NULL) return(NULL);
455 /* only for combining lists, not for authentication */
456 if (strcmp(l->who, s) == 0)
463 static Access_Entry_4 *
465 Access_Entry_4 *p_list,
466 Access_Entry_4 *p_head,
471 Access_Entry_4 *h = p_head;
473 while (p_list != NULL)
475 /* Delay to put the WORLD into the combined list because
476 * in_access_list() may return wrong result.
478 if (strcmp (p_list->who, WORLD) == 0)
482 /* The user is not in the combined list, add to list. */
483 if ((a = in_access_list (h, p_list->who)) == NULL)
485 a = _DtCm_make_access_entry4(p_list->who, type);
489 a->access_type |= type;
491 p_list = p_list->next;
496 static CSA_return_code
503 int worldaccess = 0, useraccess = 0;
504 Access_Entry_4 *alist;
506 /* first check to see if the user is the owner of the calendar */
507 if (_DtCmsIsFileOwner(cal->owner, sender, target)) {
508 *access = CSA_OWNER_RIGHTS;
509 return (CSA_SUCCESS);
512 for (alist = cal->alist; alist != NULL; alist = alist->next) {
513 if (strcmp(alist->who, WORLD) == 0)
514 worldaccess = alist->access_type;
515 else if (_DtCmIsSameUser(sender, alist->who)) {
516 useraccess = alist->access_type;
521 *access = worldaccess | useraccess;
522 return (CSA_SUCCESS);
525 static CSA_return_code
532 cms_access_entry *alist;
533 cms_attribute_value *owner;
534 int worldaccess = 0, useraccess = 0;
537 /* first check to see if the user is the owner of the calendar */
538 owner = cal->attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].value;
539 isowner = _DtCmsIsFileOwner(owner->item.calendar_user_value, sender,
542 if (isowner && cal->checkowner == B_FALSE) {
543 *access = CSA_OWNER_RIGHTS;
544 return (CSA_SUCCESS);
547 alist = cal->attrs[CSA_CAL_ATTR_ACCESS_LIST_I].value->\
548 item.access_list_value;
551 *access = worldaccess | useraccess;
552 return (CSA_E_NO_AUTHORITY);
555 for (; alist != NULL; alist = alist->next) {
556 if (strcmp(alist->user, WORLD) == 0)
557 worldaccess = alist->rights;
558 else if (_DtCmIsSameUser(sender, alist->user)) {
559 useraccess = alist->rights;
564 *access = worldaccess | useraccess;
565 return (CSA_SUCCESS);