|
Chris PeBenito |
473ea7 |
#include <unistd.h>
|
|
Chris PeBenito |
473ea7 |
#include <fcntl.h>
|
|
Chris PeBenito |
473ea7 |
#include <stdlib.h>
|
|
Chris PeBenito |
473ea7 |
#include <string.h>
|
|
Chris PeBenito |
473ea7 |
#include <stdio.h>
|
|
Chris PeBenito |
473ea7 |
#include <ctype.h>
|
|
Chris PeBenito |
473ea7 |
#include <selinux/selinux.h>
|
|
Chris PeBenito |
473ea7 |
#include <selinux/context.h>
|
|
Chris PeBenito |
473ea7 |
#include "selinux_internal.h"
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
/* Process line from seusers.conf and split into its fields.
|
|
Chris PeBenito |
473ea7 |
Returns 0 on success, -1 on comments, and -2 on error. */
|
|
Chris PeBenito |
473ea7 |
static int process_seusers(const char *buffer,
|
|
Chris PeBenito |
473ea7 |
char **luserp,
|
|
Chris PeBenito |
473ea7 |
char **seuserp,
|
|
Chris PeBenito |
473ea7 |
char **levelp,
|
|
Chris PeBenito |
473ea7 |
int mls_enabled)
|
|
Chris PeBenito |
473ea7 |
{
|
|
Chris PeBenito |
473ea7 |
char *newbuf = strdup(buffer);
|
|
Chris PeBenito |
473ea7 |
char *luser = NULL, *seuser = NULL, *level = NULL;
|
|
Chris PeBenito |
473ea7 |
char *start, *end;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
if (!newbuf)
|
|
Chris PeBenito |
473ea7 |
goto err;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
start = newbuf;
|
|
Chris PeBenito |
473ea7 |
while (isspace(*start))
|
|
Chris PeBenito |
473ea7 |
start++;
|
|
Chris PeBenito |
5a3b36 |
if (*start == '#' || *start == 0) {
|
|
Chris PeBenito |
473ea7 |
free(newbuf);
|
|
Chris PeBenito |
5a3b36 |
return -1; /* Comment or empty line, skip over */
|
|
Chris PeBenito |
473ea7 |
}
|
|
Chris PeBenito |
473ea7 |
end = strchr(start, ':');
|
|
Chris PeBenito |
473ea7 |
if (!end)
|
|
Chris PeBenito |
473ea7 |
goto err;
|
|
Chris PeBenito |
473ea7 |
*end = 0;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
luser = strdup(start);
|
|
Chris PeBenito |
473ea7 |
if (!luser)
|
|
Chris PeBenito |
473ea7 |
goto err;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
start = end+1;
|
|
Chris PeBenito |
473ea7 |
end = strchr(start, ':');
|
|
Chris PeBenito |
473ea7 |
if (!end) {
|
|
Chris PeBenito |
473ea7 |
if (mls_enabled)
|
|
Chris PeBenito |
473ea7 |
goto err; /* no MLS level and MLS is enabled */
|
|
Chris PeBenito |
473ea7 |
/* MLS is disabled, so :level suffix not required. */
|
|
Chris PeBenito |
473ea7 |
end = start;
|
|
Chris PeBenito |
473ea7 |
while (*end && !isspace(*end))
|
|
Chris PeBenito |
473ea7 |
end++;
|
|
Chris PeBenito |
473ea7 |
}
|
|
Chris PeBenito |
473ea7 |
*end = 0;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
seuser = strdup(start);
|
|
Chris PeBenito |
473ea7 |
if (!seuser)
|
|
Chris PeBenito |
473ea7 |
goto err;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
if (!mls_enabled)
|
|
Chris PeBenito |
473ea7 |
goto out; /* skip any MLS level */
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
start = ++end;
|
|
Chris PeBenito |
473ea7 |
while (*end && !isspace(*end))
|
|
Chris PeBenito |
473ea7 |
end++;
|
|
Chris PeBenito |
473ea7 |
*end = 0;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
level = strdup(start);
|
|
Chris PeBenito |
473ea7 |
if (!level)
|
|
Chris PeBenito |
473ea7 |
goto err;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
out:
|
|
Chris PeBenito |
473ea7 |
free(newbuf);
|
|
Chris PeBenito |
473ea7 |
*luserp = luser;
|
|
Chris PeBenito |
473ea7 |
*seuserp = seuser;
|
|
Chris PeBenito |
473ea7 |
*levelp = level;
|
|
Chris PeBenito |
473ea7 |
return 0;
|
|
Chris PeBenito |
473ea7 |
err:
|
|
Chris PeBenito |
473ea7 |
free(newbuf);
|
|
Chris PeBenito |
473ea7 |
free(luser);
|
|
Chris PeBenito |
473ea7 |
free(seuser);
|
|
Chris PeBenito |
473ea7 |
free(level);
|
|
Chris PeBenito |
473ea7 |
return -2; /* error */
|
|
Chris PeBenito |
473ea7 |
}
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
int require_seusers hidden = 0;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
int getseuserbyname(const char *name, char **r_seuser, char **r_level) {
|
|
Chris PeBenito |
473ea7 |
FILE *cfg=NULL;
|
|
Chris PeBenito |
473ea7 |
size_t size=0;
|
|
Chris PeBenito |
473ea7 |
char *buffer=NULL;
|
|
Chris PeBenito |
473ea7 |
int rc;
|
|
Chris PeBenito |
473ea7 |
unsigned long lineno = 0;
|
|
Chris PeBenito |
473ea7 |
int mls_enabled = is_selinux_mls_enabled();
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
char *username=NULL;
|
|
Chris PeBenito |
473ea7 |
char *seuser=NULL;
|
|
Chris PeBenito |
473ea7 |
char *level=NULL;
|
|
Chris PeBenito |
473ea7 |
char *defaultseuser=NULL;
|
|
Chris PeBenito |
473ea7 |
char *defaultlevel=NULL;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
cfg = fopen(selinux_usersconf_path(), "r");
|
|
Chris PeBenito |
5a3b36 |
if (!cfg)
|
|
Chris PeBenito |
5a3b36 |
goto nomatch;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
while (getline(&buffer, &size, cfg) > 0) {
|
|
Chris PeBenito |
473ea7 |
++lineno;
|
|
Chris PeBenito |
473ea7 |
rc = process_seusers(buffer, &username, &seuser, &level, mls_enabled);
|
|
Chris PeBenito |
473ea7 |
if (rc == -1)
|
|
Chris PeBenito |
473ea7 |
continue; /* comment, skip */
|
|
Chris PeBenito |
473ea7 |
if (rc == -2) {
|
|
Chris PeBenito |
473ea7 |
fprintf(stderr, "%s: error on line %lu, skipping...\n",
|
|
Chris PeBenito |
473ea7 |
selinux_usersconf_path(), lineno);
|
|
Chris PeBenito |
473ea7 |
continue;
|
|
Chris PeBenito |
473ea7 |
}
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
if (!strcmp(username, name))
|
|
Chris PeBenito |
473ea7 |
break;
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
if (!defaultseuser && !strcmp(username,"default")) {
|
|
Chris PeBenito |
473ea7 |
free(username);
|
|
Chris PeBenito |
473ea7 |
defaultseuser = seuser;
|
|
Chris PeBenito |
473ea7 |
defaultlevel = level;
|
|
Chris PeBenito |
473ea7 |
} else {
|
|
Chris PeBenito |
473ea7 |
free(username);
|
|
Chris PeBenito |
473ea7 |
free(seuser);
|
|
Chris PeBenito |
473ea7 |
free(level);
|
|
Chris PeBenito |
473ea7 |
}
|
|
Chris PeBenito |
473ea7 |
seuser=NULL;
|
|
Chris PeBenito |
473ea7 |
}
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
if (buffer)
|
|
Chris PeBenito |
473ea7 |
free(buffer);
|
|
Chris PeBenito |
473ea7 |
fclose(cfg);
|
|
Chris PeBenito |
5a3b36 |
|
|
Chris PeBenito |
473ea7 |
if (seuser) {
|
|
Chris PeBenito |
473ea7 |
free(username);
|
|
Chris PeBenito |
473ea7 |
free(defaultseuser);
|
|
Chris PeBenito |
473ea7 |
free(defaultlevel);
|
|
Chris PeBenito |
473ea7 |
*r_seuser = seuser;
|
|
Chris PeBenito |
473ea7 |
*r_level = level;
|
|
Chris PeBenito |
473ea7 |
return 0;
|
|
Chris PeBenito |
473ea7 |
}
|
|
Chris PeBenito |
473ea7 |
|
|
Chris PeBenito |
473ea7 |
if (defaultseuser) {
|
|
Chris PeBenito |
473ea7 |
*r_seuser = defaultseuser;
|
|
Chris PeBenito |
473ea7 |
*r_level = defaultlevel;
|
|
Chris PeBenito |
473ea7 |
return 0;
|
|
Chris PeBenito |
473ea7 |
}
|
|
Chris PeBenito |
5a3b36 |
|
|
Chris PeBenito |
5a3b36 |
nomatch:
|
|
Chris PeBenito |
5a3b36 |
if (require_seusers)
|
|
Chris PeBenito |
5a3b36 |
return -1;
|
|
Chris PeBenito |
5a3b36 |
|
|
Chris PeBenito |
5a3b36 |
/* Fall back to the Linux username and no level. */
|
|
Chris PeBenito |
5a3b36 |
*r_seuser = strdup(name);
|
|
Chris PeBenito |
5a3b36 |
if (!(*r_seuser))
|
|
Chris PeBenito |
5a3b36 |
return -1;
|
|
Chris PeBenito |
5a3b36 |
*r_level = NULL;
|
|
Chris PeBenito |
5a3b36 |
return 0;
|
|
Chris PeBenito |
473ea7 |
}
|