16cd6a6acSopenharmony_ci#include <unistd.h>
26cd6a6acSopenharmony_ci#include <sys/types.h>
36cd6a6acSopenharmony_ci#include <fcntl.h>
46cd6a6acSopenharmony_ci#include <stdlib.h>
56cd6a6acSopenharmony_ci#include <stdio.h>
66cd6a6acSopenharmony_ci#include <errno.h>
76cd6a6acSopenharmony_ci#include <string.h>
86cd6a6acSopenharmony_ci#include "selinux_internal.h"
96cd6a6acSopenharmony_ci#include "policy.h"
106cd6a6acSopenharmony_ci#include <limits.h>
116cd6a6acSopenharmony_ci#include "callbacks.h"
126cd6a6acSopenharmony_ci
136cd6a6acSopenharmony_ciint security_compute_user_raw(const char * scon,
146cd6a6acSopenharmony_ci			      const char *user, char *** con)
156cd6a6acSopenharmony_ci{
166cd6a6acSopenharmony_ci	char path[PATH_MAX];
176cd6a6acSopenharmony_ci	char **ary;
186cd6a6acSopenharmony_ci	char *buf, *ptr;
196cd6a6acSopenharmony_ci	size_t size;
206cd6a6acSopenharmony_ci	int fd, ret;
216cd6a6acSopenharmony_ci	unsigned int i, nel;
226cd6a6acSopenharmony_ci
236cd6a6acSopenharmony_ci	if (!selinux_mnt) {
246cd6a6acSopenharmony_ci		errno = ENOENT;
256cd6a6acSopenharmony_ci		return -1;
266cd6a6acSopenharmony_ci	}
276cd6a6acSopenharmony_ci
286cd6a6acSopenharmony_ci	selinux_log(SELINUX_WARNING, "Direct use of security_compute_user() is deprecated, switch to get_ordered_context_list()\n");
296cd6a6acSopenharmony_ci
306cd6a6acSopenharmony_ci	snprintf(path, sizeof path, "%s/user", selinux_mnt);
316cd6a6acSopenharmony_ci	fd = open(path, O_RDWR | O_CLOEXEC);
326cd6a6acSopenharmony_ci	if (fd < 0)
336cd6a6acSopenharmony_ci		return -1;
346cd6a6acSopenharmony_ci
356cd6a6acSopenharmony_ci	size = selinux_page_size;
366cd6a6acSopenharmony_ci	buf = malloc(size);
376cd6a6acSopenharmony_ci	if (!buf) {
386cd6a6acSopenharmony_ci		ret = -1;
396cd6a6acSopenharmony_ci		goto out;
406cd6a6acSopenharmony_ci	}
416cd6a6acSopenharmony_ci
426cd6a6acSopenharmony_ci	ret = snprintf(buf, size, "%s %s", scon, user);
436cd6a6acSopenharmony_ci	if (ret < 0 || (size_t)ret >= size) {
446cd6a6acSopenharmony_ci		errno = EOVERFLOW;
456cd6a6acSopenharmony_ci		ret = -1;
466cd6a6acSopenharmony_ci		goto out2;
476cd6a6acSopenharmony_ci	}
486cd6a6acSopenharmony_ci
496cd6a6acSopenharmony_ci	ret = write(fd, buf, strlen(buf));
506cd6a6acSopenharmony_ci	if (ret < 0)
516cd6a6acSopenharmony_ci		goto out2;
526cd6a6acSopenharmony_ci
536cd6a6acSopenharmony_ci	memset(buf, 0, size);
546cd6a6acSopenharmony_ci	ret = read(fd, buf, size - 1);
556cd6a6acSopenharmony_ci	if (ret < 0)
566cd6a6acSopenharmony_ci		goto out2;
576cd6a6acSopenharmony_ci
586cd6a6acSopenharmony_ci	if (sscanf(buf, "%u", &nel) != 1) {
596cd6a6acSopenharmony_ci		ret = -1;
606cd6a6acSopenharmony_ci		goto out2;
616cd6a6acSopenharmony_ci	}
626cd6a6acSopenharmony_ci
636cd6a6acSopenharmony_ci	ary = malloc((nel + 1) * sizeof(char *));
646cd6a6acSopenharmony_ci	if (!ary) {
656cd6a6acSopenharmony_ci		ret = -1;
666cd6a6acSopenharmony_ci		goto out2;
676cd6a6acSopenharmony_ci	}
686cd6a6acSopenharmony_ci
696cd6a6acSopenharmony_ci	ptr = buf + strlen(buf) + 1;
706cd6a6acSopenharmony_ci	for (i = 0; i < nel; i++) {
716cd6a6acSopenharmony_ci		ary[i] = strdup(ptr);
726cd6a6acSopenharmony_ci		if (!ary[i]) {
736cd6a6acSopenharmony_ci			freeconary(ary);
746cd6a6acSopenharmony_ci			ret = -1;
756cd6a6acSopenharmony_ci			goto out2;
766cd6a6acSopenharmony_ci		}
776cd6a6acSopenharmony_ci		ptr += strlen(ptr) + 1;
786cd6a6acSopenharmony_ci	}
796cd6a6acSopenharmony_ci	ary[nel] = NULL;
806cd6a6acSopenharmony_ci	*con = ary;
816cd6a6acSopenharmony_ci	ret = 0;
826cd6a6acSopenharmony_ci      out2:
836cd6a6acSopenharmony_ci	free(buf);
846cd6a6acSopenharmony_ci      out:
856cd6a6acSopenharmony_ci	close(fd);
866cd6a6acSopenharmony_ci	return ret;
876cd6a6acSopenharmony_ci}
886cd6a6acSopenharmony_ci
896cd6a6acSopenharmony_ci
906cd6a6acSopenharmony_ciint security_compute_user(const char * scon,
916cd6a6acSopenharmony_ci			  const char *user, char *** con)
926cd6a6acSopenharmony_ci{
936cd6a6acSopenharmony_ci	int ret;
946cd6a6acSopenharmony_ci	char * rscon;
956cd6a6acSopenharmony_ci
966cd6a6acSopenharmony_ci	if (selinux_trans_to_raw_context(scon, &rscon))
976cd6a6acSopenharmony_ci		return -1;
986cd6a6acSopenharmony_ci
996cd6a6acSopenharmony_ci	ret = security_compute_user_raw(rscon, user, con);
1006cd6a6acSopenharmony_ci
1016cd6a6acSopenharmony_ci	freecon(rscon);
1026cd6a6acSopenharmony_ci	if (!ret) {
1036cd6a6acSopenharmony_ci		char **ptr, *tmpcon;
1046cd6a6acSopenharmony_ci		for (ptr = *con; *ptr; ptr++) {
1056cd6a6acSopenharmony_ci			if (selinux_raw_to_trans_context(*ptr, &tmpcon)) {
1066cd6a6acSopenharmony_ci				freeconary(*con);
1076cd6a6acSopenharmony_ci				*con = NULL;
1086cd6a6acSopenharmony_ci				return -1;
1096cd6a6acSopenharmony_ci			}
1106cd6a6acSopenharmony_ci			freecon(*ptr);
1116cd6a6acSopenharmony_ci			*ptr = tmpcon;
1126cd6a6acSopenharmony_ci		}
1136cd6a6acSopenharmony_ci	}
1146cd6a6acSopenharmony_ci
1156cd6a6acSopenharmony_ci	return ret;
1166cd6a6acSopenharmony_ci}
1176cd6a6acSopenharmony_ci
118