1 /* $XConsortium: access.c /main/5 1996/10/08 16:41:05 barstow $ */
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company
4 * (c) Copyright 1993, 1994 International Business Machines Corp.
5 * (c) Copyright 1993, 1994 Novell, Inc.
6 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
10 #include <EUSCompat.h>
16 #include <sys/systeminfo.h>
25 #define NUM_CACHE 50 /* cache for unix user name */
29 typedef struct uname_cache {
30 uid_t uid; /* unix user id */
31 char *name; /* user name */
32 struct uname_cache *next;
35 static Uname_cache *ucache_list = NULL;
37 /******************************************************************************
38 * forward declaration of static functions used within the file
39 ******************************************************************************/
40 static Uname_cache * in_u_cache(uid_t uid);
41 static char * get_uname(uid_t uid);
42 static Access_Entry_4 * in_access_list(Access_Entry_4 *l, char *s);
43 static Access_Entry_4 * combine_access_list(Access_Entry_4 *p_list,
44 Access_Entry_4 *p_head, int type, int *p_world);
45 static CSA_return_code _GetV4AccessRights(_DtCmsCalendar *cal, char *target,
46 char *sender, uint *access);
47 static CSA_return_code _GetV5AccessRights(_DtCmsCalendar *cal, char *target,
48 char *sender, uint *access);
50 /*****************************************************************************
51 * extern functions used in the library
52 *****************************************************************************/
55 * If the requester is the owner, "*sender" will be set to NULL.
57 extern CSA_return_code
58 _DtCmsV4LoadAndCheckAccess(
59 struct svc_req *svcrq,
67 if (target == NULL || sender == NULL || cal == NULL)
68 return (CSA_E_INVALID_PARAMETER);
70 if ((stat = _DtCmsGetClientInfo(svcrq, sender)) != CSA_SUCCESS)
73 if ((stat = _DtCmsGetCalendarByName(target, B_TRUE, cal))
77 if ((*cal)->fversion == _DtCMS_VERSION1)
78 return (_GetV4AccessRights(*cal, target, *sender, access));
80 return (_GetV5AccessRights(*cal, target, *sender, access));
85 * If the requester is the owner, "*p_src" will be set to NULL.
87 extern CSA_return_code
88 _DtCmsV5LoadAndCheckAccess(
89 struct svc_req *svcrq,
96 cms_access_entry *alist;
97 cms_attribute_value *owner;
98 int worldaccess = 0, useraccess = 0;
102 if (target == NULL || sender == NULL || cal == NULL)
103 return (CSA_E_INVALID_PARAMETER);
105 if ((stat = _DtCmsGetClientInfo(svcrq, sender)) != CSA_SUCCESS)
108 if ((stat = _DtCmsGetCalendarByName(target, B_TRUE, cal))
112 if ((*cal)->fversion == _DtCMS_VERSION1)
113 return (_GetV4AccessRights(*cal, target, *sender, access));
115 return (_GetV5AccessRights(*cal, target, *sender, access));
118 extern CSA_return_code
119 _DtCmsGetClientInfo(struct svc_req *svcrq, char **source)
123 struct authunix_parms *unix_cred;
127 return (CSA_E_INVALID_PARAMETER);
130 switch (svcrq->rq_cred.oa_flavor) {
132 unix_cred = (struct authunix_parms *) svcrq->rq_clntcred;
133 if (unix_cred == NULL)
134 return (CSA_E_NO_AUTHORITY);
135 if ((name = get_uname (unix_cred->aup_uid)) == NULL)
136 return (CSA_E_INSUFFICIENT_MEMORY);
137 if ((uname = malloc(strlen(name) +
138 strlen(unix_cred->aup_machname) + 2)) == NULL)
139 return (CSA_E_INSUFFICIENT_MEMORY);
141 sprintf(uname, "%s@%s", name, unix_cred->aup_machname);
143 return (CSA_SUCCESS);
148 svcerr_weakauth(svcrq->rq_xprt);
149 return (CSA_E_NO_AUTHORITY);
154 * good format of owner and user assumed:
155 * owner: user[@host[.domain]]
156 * user: user@host[.domain]
157 * target: name@host[.domain]
160 _DtCmsIsFileOwner(char *owner, char *user, char *target)
162 char *ptr1, *ptr2, *ptr3;
165 fprintf(stderr, "rpc.cmsd: %s, %s = %s, %s = %s, %s = %s\n",
167 "owner", ((owner == NULL) ? "NULL" : owner),
168 "user", ((user == NULL) ? "NULL" : user),
169 "target", ((target == NULL) ? "NULL" : target));
172 if (owner == NULL || user == NULL || target == NULL)
175 ptr1 = _DtCmGetPrefix(owner, '@');
176 ptr2 = _DtCmGetPrefix(user, '@');
177 if (strcmp(ptr1, ptr2)) {
185 /* check domain if domain info is available */
187 ptr1 = strchr(user, '.');
188 ptr2 = strchr(target, '@');
190 ptr3 = strchr(ptr2, '.');
194 if (ptr1 == NULL || ptr3 == NULL)
195 /* assume that user is in the local domain */
198 return(_DtCmIsSamePath(++ptr1, ++ptr3));
202 _DtCmsShowAccessList(Access_Entry_4 *l)
205 fprintf(stderr, "Access: %s(%c%c%c)\n", l->who,
206 l->access_type & access_read_4 ? 'r' : '_',
207 l->access_type & access_write_4 ? 'w' : '_',
208 l->access_type & access_delete_4 ? 'd' : '_');
213 extern Access_Entry_4 *
214 _DtCmsCalendarAccessList(_DtCmsCalendar *cal)
216 int world = access_none_4;
218 Access_Entry_4 *l = NULL;
220 l = combine_access_list(GET_R_ACCESS(cal), l, access_read_4, &world);
221 l = combine_access_list(GET_W_ACCESS(cal), l, access_write_4, &world);
222 l = combine_access_list(GET_D_ACCESS(cal), l, access_delete_4, &world);
223 l = combine_access_list(GET_X_ACCESS(cal), l, access_exec_4, &world);
225 /* WORLD exists in one of the lists, add her to the combined list. */
226 if (world != access_none_4)
228 a = _DtCm_make_access_entry4(WORLD, world);
235 extern Privacy_Level_4
236 _DtCmCheckPrivacyLevel(char **p_src, Appt_4 *p_appt)
241 if (p_appt != NULL) {
243 * if p_src is the author of the appointment,
244 * it should see everything.
246 if (_DtCmIsSameUser(*p_src, p_appt->author)) {
250 return(p_appt->privacy);
256 * the user can view the entry if it has OWNER rights,
257 * the appropriate VIEW rights or he is the organizer of
258 * the entry and has ORGANIZER rights.
260 extern CSA_return_code
261 _DtCmsCheckViewAccess(char *user, uint access, cms_entry *eptr)
264 cms_attribute_value *oval, *sval;
266 need = (_DtCmsClassToViewAccess(eptr)) | CSA_OWNER_RIGHTS;
268 return (CSA_SUCCESS);
270 oval = eptr->attrs[CSA_ENTRY_ATTR_ORGANIZER_I].value;
271 sval = eptr->attrs[CSA_ENTRY_ATTR_SPONSOR_I].value;
272 if (((access & CSA_ORGANIZER_RIGHTS) &&
273 _DtCmIsSameUser(user, oval->item.calendar_user_value)) ||
274 ((access & CSA_SPONSOR_RIGHTS) && sval &&
275 _DtCmIsSameUser(user, sval->item.calendar_user_value)))
276 return (CSA_SUCCESS);
277 else if ( (need & ~CSA_OWNER_RIGHTS) == (CSA_VIEW_CONFIDENTIAL_ENTRIES) ) {
278 return (CSA_E_TIME_ONLY);
280 return (CSA_E_NO_AUTHORITY);
284 extern CSA_return_code
285 _DtCmsCheckChangeAccess(char *user, uint access, cms_entry *eptr)
288 cms_attribute_value *oval, *sval;
290 need = (_DtCmsClassToChangeAccess(eptr)) | CSA_OWNER_RIGHTS;
293 return (CSA_SUCCESS);
295 oval = eptr->attrs[CSA_ENTRY_ATTR_ORGANIZER_I].value;
296 sval = eptr->attrs[CSA_ENTRY_ATTR_SPONSOR_I].value;
297 if (((access & CSA_ORGANIZER_RIGHTS) &&
298 _DtCmIsSameUser(user, oval->item.calendar_user_value)) ||
299 ((access & CSA_SPONSOR_RIGHTS) && sval &&
300 _DtCmIsSameUser(user, sval->item.calendar_user_value)))
301 return (CSA_SUCCESS);
303 return (CSA_E_NO_AUTHORITY);
308 _DtCmsClassToViewAccess(cms_entry *entry)
310 cms_attribute_value *val;
312 val = entry->attrs[CSA_ENTRY_ATTR_CLASSIFICATION_I].value;
314 switch (val->item.uint32_value) {
315 case CSA_CLASS_PUBLIC:
316 return (CSA_VIEW_PUBLIC_ENTRIES);
317 case CSA_CLASS_PRIVATE:
318 return (CSA_VIEW_PRIVATE_ENTRIES);
319 case CSA_CLASS_CONFIDENTIAL:
320 return (CSA_VIEW_CONFIDENTIAL_ENTRIES);
325 _DtCmsClassToInsertAccess(cms_entry *entry)
327 cms_attribute_value *val;
329 val = entry->attrs[CSA_ENTRY_ATTR_CLASSIFICATION_I].value;
331 switch (val->item.uint32_value) {
332 case CSA_CLASS_PUBLIC:
333 return (CSA_INSERT_PUBLIC_ENTRIES);
334 case CSA_CLASS_PRIVATE:
335 return (CSA_INSERT_PRIVATE_ENTRIES);
336 case CSA_CLASS_CONFIDENTIAL:
337 return (CSA_INSERT_CONFIDENTIAL_ENTRIES);
342 _DtCmsClassToChangeAccess(cms_entry *entry)
344 cms_attribute_value *val;
346 val = entry->attrs[CSA_ENTRY_ATTR_CLASSIFICATION_I].value;
348 switch (val->item.uint32_value) {
349 case CSA_CLASS_PUBLIC:
350 return (CSA_CHANGE_PUBLIC_ENTRIES);
351 case CSA_CLASS_PRIVATE:
352 return (CSA_CHANGE_PRIVATE_ENTRIES);
353 case CSA_CLASS_CONFIDENTIAL:
354 return (CSA_CHANGE_CONFIDENTIAL_ENTRIES);
358 /*****************************************************************************
359 * static functions used within the file
360 *****************************************************************************/
363 in_u_cache(uid_t uid)
365 int cache = NUM_CACHE;
367 Uname_cache *p_cache;
370 p_cache = ucache_list;
371 while (p_cache != NULL)
373 if (p_cache->uid == uid)
377 /* Assume that the cache size is at least 1 */
378 p_prev->next = p_cache->next;
379 free (p_cache->name);
381 p_cache = p_prev->next;
386 p_cache = p_cache->next;
397 Uname_cache *ucache, *prev;
399 if ((ucache = in_u_cache(uid)) == NULL)
401 if ((pw = getpwuid (uid)) == NULL) {
402 /* Can't map uid to name. Don't cache the uid. */
403 sprintf (buff, "%ld", (long)uid);
404 return (strdup(buff));
407 if ((ucache = (Uname_cache *)malloc(sizeof(Uname_cache)))
411 if ((ucache->name = strdup(pw->pw_name)) == NULL) {
416 ucache->next = ucache_list;
417 ucache_list = ucache;
420 return (strdup(ucache->name));
423 static Access_Entry_4 *
424 in_access_list(Access_Entry_4 *l, char *s)
428 if (l==NULL || s==NULL) return(NULL);
430 /* only for combining lists, not for authentication */
431 if (strcmp(l->who, s) == 0)
438 static Access_Entry_4 *
440 Access_Entry_4 *p_list,
441 Access_Entry_4 *p_head,
446 Access_Entry_4 *h = p_head;
448 while (p_list != NULL)
450 /* Delay to put the WORLD into the combined list because
451 * in_access_list() may return wrong result.
453 if (strcmp (p_list->who, WORLD) == 0)
457 /* The user is not in the combined list, add to list. */
458 if ((a = in_access_list (h, p_list->who)) == NULL)
460 a = _DtCm_make_access_entry4(p_list->who, type);
464 a->access_type |= type;
466 p_list = p_list->next;
471 static CSA_return_code
478 int worldaccess = 0, useraccess = 0;
479 Access_Entry_4 *alist;
481 /* first check to see if the user is the owner of the calendar */
482 if (_DtCmsIsFileOwner(cal->owner, sender, target)) {
483 *access = CSA_OWNER_RIGHTS;
484 return (CSA_SUCCESS);
487 for (alist = cal->alist; alist != NULL; alist = alist->next) {
488 if (strcmp(alist->who, WORLD) == 0)
489 worldaccess = alist->access_type;
490 else if (_DtCmIsSameUser(sender, alist->who)) {
491 useraccess = alist->access_type;
496 *access = worldaccess | useraccess;
497 return (CSA_SUCCESS);
500 static CSA_return_code
507 cms_access_entry *alist;
508 cms_attribute_value *owner;
509 int worldaccess = 0, useraccess = 0;
512 /* first check to see if the user is the owner of the calendar */
513 owner = cal->attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].value;
514 isowner = _DtCmsIsFileOwner(owner->item.calendar_user_value, sender,
517 if (isowner && cal->checkowner == B_FALSE) {
518 *access = CSA_OWNER_RIGHTS;
519 return (CSA_SUCCESS);
522 alist = cal->attrs[CSA_CAL_ATTR_ACCESS_LIST_I].value->\
523 item.access_list_value;
526 *access = worldaccess | useraccess;
527 return (CSA_E_NO_AUTHORITY);
530 for (; alist != NULL; alist = alist->next) {
531 if (strcmp(alist->user, WORLD) == 0)
532 worldaccess = alist->rights;
533 else if (_DtCmIsSameUser(sender, alist->user)) {
534 useraccess = alist->rights;
539 *access = worldaccess | useraccess;
540 return (CSA_SUCCESS);