--- nsalibselinux/include/selinux/selinux.h 2009-04-08 09:06:23.000000000 -0400 +++ libselinux-2.0.81/include/selinux/selinux.h 2009-05-18 14:04:07.000000000 -0400 @@ -544,6 +547,14 @@ Caller must free the returned strings via free. */ extern int getseuserbyname(const char *linuxuser, char **seuser, char **level); +/* Get the SELinux username and level to use for a given Linux username and service. + These values may then be passed into the get_ordered_context_list* + and get_default_context* functions to obtain a context for the user. + Returns 0 on success or -1 otherwise. + Caller must free the returned strings via free. */ +extern int getseuser(const char *username, const char *service, + char **r_seuser, char **r_level); + /* Compare two file contexts, return 0 if equivalent. */ int selinux_file_context_cmp(const security_context_t a, const security_context_t b); --- nsalibselinux/src/seusers.c 2009-03-06 14:41:45.000000000 -0500 +++ libselinux-2.0.81/src/seusers.c 2009-05-18 14:04:07.000000000 -0400 @@ -243,3 +243,67 @@ *r_level = NULL; return 0; } + +int getseuser(const char *username, const char *service, + char **r_seuser, char **r_level) { + int ret = -1; + int len = 0; + char *seuser = NULL; + char *level = NULL; + char *buffer = NULL; + size_t size = 0; + size_t lineno = 0; + char *rec = NULL; + char *path=NULL; + if (asprintf(&path,"%s/logins/%s", selinux_policy_root(), username) < 0) + goto err; + FILE *fp = fopen(path, "r"); + free(path); + if (fp == NULL) goto err; + __fsetlocking(fp, FSETLOCKING_BYCALLER); + while (getline(&buffer, &size, fp) > 0) { + ++lineno; + + if (strncmp(buffer, "*:", 2) == 0) { + free(rec); + rec = strdup(buffer); + continue; + } + len = strlen(service); + if ((strncmp(buffer, service, len) == 0) && + (buffer[len] == ':')) { + free(rec); + rec = strdup(buffer); + break; + } + } + + if (! rec) goto err; + seuser = strchr(rec, ':'); + if (! seuser) goto err; + + seuser++; + level = strchr(seuser, ':'); + *level = 0; + level++; + *r_seuser = strdup(seuser); + if (! *r_seuser) goto err; + + len = strlen(level); + if (len && level[len-1] == '\n') + level[len-1] = 0; + + *r_level = strdup(level); + if (! *r_level) { + free(*r_seuser); + goto err; + } + ret = 0; + + err: + free(buffer); + if (fp) fclose(fp); + free(rec); + + return (ret ? getseuserbyname(username, r_seuser, r_level) : ret); +}