Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Stone <michael@laptop.org>2008-01-29 00:31:24 (GMT)
committer Michael Stone <michael@laptop.org>2008-01-29 00:31:24 (GMT)
commit2e8cf5ba5a2236a4d75ea994f1ed84177d062509 (patch)
treef98fd1dc8c5cc0e0d3173eee52f2100551d5f57a
parent5426c37456b3e12105ed46713e544d0aea81b392 (diff)
Modularize.
-rw-r--r--Makefile40
-rw-r--r--buf.c83
-rw-r--r--buf.h2
-rw-r--r--cgen.h7
-rw-r--r--group.c56
-rw-r--r--nat.c46
-rw-r--r--nat.h3
-rw-r--r--nss-rainbow.c179
-rw-r--r--test_nat.c20
9 files changed, 330 insertions, 106 deletions
diff --git a/Makefile b/Makefile
index 8475b6d..0ccbe95 100644
--- a/Makefile
+++ b/Makefile
@@ -6,20 +6,42 @@ WARNFLAGS = \
-Wextra -Wstrict-aliasing=2 \
-Wunsafe-loop-optimizations
-all: libnss_rainbow.so.2 list
+# declarations
-list: list.c
- $(CC) -g -o $@ $<
+RAINBOW_OBJS = nss-rainbow.o buf.o nat.o
+LIST_OBJS = list.o
+TEST_NAT_OBJS = test_nat.o nat.o
+BINARIES = libnss_rainbow.so.2 list test_nat
-libnss_rainbow.so.2: nss-rainbow.o
- $(CC) -shared -o $@ -Wl,-soname,$@ $<
+# targets
-nss-rainbow.o: nss-rainbow.c
- $(CC) -g -std=gnu99 $(WARNFLAGS) -o $@ -c $<
+all: $(BINARIES)
clean:
- rm -f libnss_rainbow.so.2 nss-rainbow.o list
+ rm -f $(BINARIES) $(RAINBOW_OBJS) $(LIST_OBJS) $(TEST_NAT_OBJS)
-.PHONY: clean
+install:
+ install -D -m 755 libnss_rainbow.so.2 $(DESTDIR)/usr/lib
+
+
+# objects
+
+%.o: %.c
+ $(CC) -g -std=gnu99 $(WARNFLAGS) -c -o $@ $<
+
+
+# linked binaries
+
+test_nat: $(TEST_NAT_OBJS)
+ $(CC) -g -std=gnu99 $(WARNFLAGS) -o $@ $^
+
+list: $(LIST_OBJS)
+ $(CC) -g -std=gnu99 $(WARNFLAGS) -o $@ $^
+
+libnss_rainbow.so.2: $(RAINBOW_OBJS)
+ $(CC) -shared -o $@ -Wl,-soname,$@ $^
+
+
+.PHONY: clean install
# vim: noet sts=4 ts=4 sw=4 :
diff --git a/buf.c b/buf.c
new file mode 100644
index 0000000..09a6e8e
--- /dev/null
+++ b/buf.c
@@ -0,0 +1,83 @@
+#include <errno.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdarg.h>
+
+
+#include "cgen.h"
+#include "buf.h"
+
+
+int write_buf(char** buf, size_t * buflen, const char* val)
+{
+ /* write_buf will not write outside of (*buf)[0..(*buflen-1)]
+ * if *buflen > strlen(val), then write_buf will ensure that *buf points to a null-terminated string.
+ * on success, write_buf will advance *buf to the next free char,
+ * set *buflen to indicate the quantity of remaining space,
+ * and return 0.
+ * on error, write_buf will set errno, return 1, and will not modify *buf or *buflen.
+ * *buf and val should not overlap.
+ */
+
+ LET(size_t copy_amt = strlen(val) + 1, copy_amt == 0,
+ "Integer overflow.", out_err_overflow);
+
+ if (*buflen < copy_amt)
+ goto out_err_range;
+
+ memcpy(*buf, val, copy_amt);
+
+ *buf += copy_amt;
+ *buflen -= copy_amt;
+ return 0;
+
+out_err_overflow:
+ errno = EOVERFLOW;
+ return 1;
+
+out_err_range:
+ errno = ERANGE;
+ return 1;
+}
+
+int format_buf(char** buf, size_t* buflen, const char* fmt, ...)
+{
+ /* format_buf will not write outside of (*buf)[0..(*buflen-1)]
+ * if *buflen > 0, format_buf will ensure that *buf points to a null-terminated string.
+ * on success, format_buf will advance *buf to the next free char,
+ * set *buflen to indicate the quantity of remaining space,
+ * and return 0.
+ * on error, format_buf will set errno, return 1, and will not modify *buf or *buflen.
+ * *buf should know overlap with fmt or any optional arguments.
+ */
+ if (*buflen < 1)
+ {
+ errno = ERANGE;
+ return 1;
+ }
+
+ size_t safe_buflen = *buflen - 1;
+
+ va_list ap;
+ va_start(ap, fmt);
+ int status = vsnprintf(*buf, safe_buflen, fmt, ap);
+ SAVE_ERR(va_end(ap));
+
+ if (status < 0)
+ goto out_err;
+
+ size_t written = (size_t) status;
+ if (safe_buflen < written) {
+ errno = ERANGE;
+ goto out_err;
+ }
+
+ *buf += written+1;
+ *buflen -= written+1;
+ return 0;
+
+out_err:
+ (*buf)[safe_buflen] = '\0';
+ return 1;
+}
diff --git a/buf.h b/buf.h
new file mode 100644
index 0000000..0767df1
--- /dev/null
+++ b/buf.h
@@ -0,0 +1,2 @@
+int write_buf(char** buf, size_t * buflen, const char* val);
+int format_buf(char** buf, size_t* buflen, const char* fmt, ...);
diff --git a/cgen.h b/cgen.h
new file mode 100644
index 0000000..38e7a71
--- /dev/null
+++ b/cgen.h
@@ -0,0 +1,7 @@
+#define STATIC_ASSERT(expr) extern char __static_assertion_failed [(expr) ? 1 : -1]
+#define SAVE_ERR(EXPR) {int __errno_save = errno; EXPR; errno = __errno_save;}
+#define __XSTRING(X) __STRING(X)
+#define PERROR(msg) {int __errno_cache = errno; syslog(LOG_ERR, "%s|%d| %s: %s\nError %d: %s", __FILE__, __LINE__, __func__, msg, __errno_cache, strerror(__errno_cache));}
+#define CHK(EXPR, MSG, ERR_LABEL) {if(EXPR) { PERROR(MSG); goto ERR_LABEL;}}
+#define LET(LETEXPR, CONDEXPR, MSG, ERR_LABEL) LETEXPR; if (CONDEXPR) { PERROR(MSG); goto ERR_LABEL;}
+#define TST(EXPR, ERRNO, MSG, ERR_LABEL) if (EXPR) {errno = ERRNO; PERROR(MSG); goto ERR_LABEL;}
diff --git a/group.c b/group.c
new file mode 100644
index 0000000..e7a79f6
--- /dev/null
+++ b/group.c
@@ -0,0 +1,56 @@
+/*
+enum nss_status
+_nss_rainbow_initgroups_dyn(const char *user, gid_t gid, long int *start, long int *size, gid_t **groupsp, long int limit, int *errnop) {
+ openlog("nss-rainbow", LOG_PID, LOG_LOCAL0);
+ PERROR("Hallo!");
+ return NSS_STATUS_SUCCESS;
+}
+
+ if (uid < 10000)
+ return NSS_STATUS_NOTFOUND;
+
+ int pathlen = 1024;
+ char pathdata[1024], *pathbuf = pathdata;
+
+
+ result->pw_dir = buf;
+ CHK(format_buf(&pathbuf, &pathlen, "/home/olpc/isolation/1/uid_to_home_dir/%d", uid) == 0,
+ "Unable to calculate home dir.", out_error_errno);
+
+ struct stat st;
+ CHK(stat(result->pw_dir, &st) == -1,
+ "Stat failed for homebuf.", out_error_errno);
+ result->pw_uid = uid;
+ result->pw_gid = st.st_gid;
+
+ (*groupsp)[*start] =
+}
+
+enum nss_status _nss_rainbow_setgrent(void) {
+ openlog("nss-rainbow", LOG_PID, LOG_LOCAL0);
+ PERROR("Hallo!");
+ return NSS_STATUS_SUCCESS; }
+enum nss_status _nss_rainbow_endgrent(void) {
+ openlog("nss-rainbow", LOG_PID, LOG_LOCAL0);
+ PERROR("Hallo!");
+ return NSS_STATUS_SUCCESS; }
+
+enum nss_status
+_nss_rainbow_getgrent_r(struct group *result, char *buf, size_t buflen, int *errnop) {
+ openlog("nss-rainbow", LOG_PID, LOG_LOCAL0);
+ PERROR("Hallo!");
+ return NSS_STATUS_NOTFOUND;
+ //Do we really need grent/grid/grnam?
+}
+
+
+enum nss_status
+_nss_rainbow_getgrgid_r(gid_t gid, struct group *gbuf, char *buf, size_t buflen, int *errnop) {
+ return NSS_STATUS_NOTFOUND;
+}
+
+enum nss_status
+_nss_rainbow_getgrnam_r(const char* name, struct group *gbuf, char *buf, size_t buflen, int *errnop) {
+ return NSS_STATUS_NOTFOUND;
+}
+*/
diff --git a/nat.c b/nat.c
new file mode 100644
index 0000000..ec76d1e
--- /dev/null
+++ b/nat.c
@@ -0,0 +1,46 @@
+#include <errno.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+
+#include "cgen.h"
+#include "nat.h"
+
+int nat_add(unsigned long* result, unsigned long arg)
+{
+ unsigned long tmp = *result + arg;
+ if (tmp < arg) {
+ errno = EOVERFLOW;
+ return 1;
+ }
+ *result = tmp;
+ return 0;
+}
+
+int nat_mult(unsigned long* result, unsigned long long arg)
+{
+ unsigned long long tmp = arg * (*result);
+ if (tmp > (unsigned long)-1) {
+ errno = EOVERFLOW;
+ return 1;
+ }
+ *result = ((unsigned long) -1) & tmp;
+ return 0;
+}
+
+int parse_nat(unsigned long* result, const char* buf, size_t buflen) {
+ unsigned long total = 0;
+ for (size_t i = 0; i < buflen; i++)
+ {
+ LET(char num = buf[i] - '0', num < 0 || num > 9,
+ "Non-decimal character in string.", out_error_inval);
+ CHK(nat_mult(&total, 10) == 1, "Multiplication overflow.", out_error_errno);
+ CHK(nat_add(&total, num) == 1, "Addition overflow.", out_error_errno);
+ }
+ *result = total;
+ return 0;
+out_error_inval:
+ errno = EINVAL;
+out_error_errno:
+ return 1;
+}
diff --git a/nat.h b/nat.h
new file mode 100644
index 0000000..ab04a89
--- /dev/null
+++ b/nat.h
@@ -0,0 +1,3 @@
+int nat_add(unsigned long* result, unsigned long arg);
+int nat_mult(unsigned long* result, unsigned long long arg);
+int parse_nat(unsigned long* result, const char* buf, size_t buflen);
diff --git a/nss-rainbow.c b/nss-rainbow.c
index c108799..a7bfd1f 100644
--- a/nss-rainbow.c
+++ b/nss-rainbow.c
@@ -5,7 +5,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
-#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
@@ -15,12 +14,10 @@
#include <syslog.h>
/* code generators */
-#define STATIC_ASSERT(expr) extern char __static_assertion_failed [(expr) ? 1 : -1]
-#define SAVE_ERR(EXPR) {int __errno_save = errno; EXPR; errno = __errno_save;}
-#define __XSTRING(X) __STRING(X)
-#define PERROR(msg) {syslog(LOG_ERR, "%s|%d| %s: %s\nError %d: %s", __FILE__, __LINE__, __func__, msg, errno, strerror(errno));}
-#define CHK(EXPR, MSG, ERR_LABEL) {if(EXPR) { PERROR(MSG); goto ERR_LABEL;}}
-#define LET(LETEXPR, CONDEXPR, MSG, ERR_LABEL) LETEXPR; if (CONDEXPR) { PERROR(MSG); goto ERR_LABEL;}
+#include "cgen.h"
+
+#include "buf.h"
+#include "nat.h"
/* constants */
#define SHELL "/sbin/nologin"
@@ -40,79 +37,6 @@ _nss_rainbow_setpwent(void) {
g_done = false;
}
-int write_buf(char** buf, size_t * buflen, const char* val)
-{
- /* write_buf will not write outside of (*buf)[0..(*buflen-1)]
- * if *buflen > strlen(val), then write_buf will ensure that *buf points to a null-terminated string.
- * on success, write_buf will advance *buf to the next free char,
- * set *buflen to indicate the quantity of remaining space,
- * and return 1.
- * on error, write_buf will set errno, return 0, and will not modify *buf or *buflen.
- * *buf and val should not overlap.
- */
-
- LET(size_t copy_amt = strlen(val) + 1, copy_amt == 0,
- "Integer overflow.", out_err_overflow);
-
- if (*buflen < copy_amt)
- goto out_err_range;
-
- memcpy(*buf, val, copy_amt);
-
- *buf += copy_amt;
- *buflen -= copy_amt;
- return 1;
-
-out_err_overflow:
- errno = EOVERFLOW;
- return 0;
-
-out_err_range:
- errno = ERANGE;
- return 0;
-}
-
-int format_buf(char** buf, size_t* buflen, const char* fmt, ...)
-{
- /* format_buf will not write outside of (*buf)[0..(*buflen-1)]
- * if *buflen > 0, format_buf will ensure that *buf points to a null-terminated string.
- * on success, format_buf will advance *buf to the next free char,
- * set *buflen to indicate the quantity of remaining space,
- * and return 1.
- * on error, format_buf will set errno, return 0, and will not modify *buf or *buflen.
- * *buf should know overlap with fmt or any optional arguments.
- */
- if (*buflen < 1)
- {
- errno = ERANGE;
- return 0;
- }
-
- size_t safe_buflen = *buflen - 1;
-
- va_list ap;
- va_start(ap, fmt);
- int status = vsnprintf(*buf, safe_buflen, fmt, ap);
- SAVE_ERR(va_end(ap));
-
- if (status < 0)
- goto out_err;
-
- size_t written = (size_t) status;
- if (safe_buflen < written) {
- errno = ERANGE;
- goto out_err;
- }
-
- *buf += written+1;
- *buflen -= written+1;
- return 1;
-
-out_err:
- (*buf)[safe_buflen] = '\0';
- return 0;
-}
-
enum nss_status
_nss_rainbow_getpwent_r(struct passwd *result, char* buf, size_t buflen, int *errnop) {
/* I'm going to interpret the reentrancy requirement on this function to mean
@@ -133,15 +57,15 @@ _nss_rainbow_getpwent_r(struct passwd *result, char* buf, size_t buflen, int *er
"Unable to retrieve $USER.", out_error_unavail);
result->pw_dir = buf;
- CHK(write_buf(&buf, &buflen, home) == 0,
+ CHK(write_buf(&buf, &buflen, home) == 1,
"Not enough buffer for $HOME.", out_error_again);
result->pw_gecos = result->pw_name = result->pw_passwd = buf;
- CHK(write_buf(&buf, &buflen, user) == 0,
+ CHK(write_buf(&buf, &buflen, user) == 1,
"Not enough buffer for $USER.", out_error_again);
result->pw_shell = buf;
- CHK(write_buf(&buf, &buflen, SHELL) == 0,
+ CHK(write_buf(&buf, &buflen, SHELL) == 1,
"Shell string constant too long.", out_error_again);
syslog(LOG_ERR, "%s success: %s (%d, %d) %s %s %s", __func__,
@@ -169,7 +93,7 @@ enum nss_status _nss_rainbow_getpwuid_r(uid_t uid, struct passwd *result, char*
return NSS_STATUS_NOTFOUND;
result->pw_dir = buf;
- CHK(format_buf(&buf, &buflen, "/home/olpc/isolation/1/uid_to_home_dir/%d", uid) == 0,
+ CHK(format_buf(&buf, &buflen, "/home/olpc/isolation/1/uid_to_home_dir/%d", uid) == 1,
"Unable to calculate home dir.", out_error_errno);
struct stat st;
@@ -179,11 +103,11 @@ enum nss_status _nss_rainbow_getpwuid_r(uid_t uid, struct passwd *result, char*
result->pw_gid = st.st_gid;
result->pw_gecos = result->pw_name = result->pw_passwd = buf;
- CHK(format_buf(&buf, &buflen, "%d", uid) == 0,
+ CHK(format_buf(&buf, &buflen, "%d", uid) == 1,
"Unable to calculate user name.", out_error_errno);
result->pw_shell = buf;
- CHK(write_buf(&buf, &buflen, SHELL) == 0,
+ CHK(write_buf(&buf, &buflen, SHELL) == 1,
"Shell string constant too long.", out_error_errno);
syslog(LOG_ERR, "%s success in uid: %s (%d, %d) %s %s %s", __func__, result->pw_name, result->pw_uid, result->pw_gid, result->pw_dir, result->pw_shell, result->pw_passwd);
@@ -195,22 +119,83 @@ out_error_errno:
return NSS_STATUS_TRYAGAIN;
}
-
enum nss_status _nss_rainbow_getpwnam_r(const char * name, struct passwd *result, char* buf, size_t buflen, int *errnop) {
openlog("nss-rainbow", LOG_PID, LOG_LOCAL0);
- char * endptr = (char*) (uintptr_t) (name + strlen(name));
+ unsigned long val;
+ CHK(parse_nat(&val, name, strlen(name)) == 1,
+ "Unable to parse name into a uid.", out_error_name);
+
+ TST(val < 10000 || val > 60000, EINVAL,
+ "Name specifies a uid outside [10000, 60000].", out_error_name);
+
+ return _nss_rainbow_getpwuid_r((uid_t)val, result, buf, buflen, errnop);
+
+out_error_name:
+ *errnop = errno;
+ return NSS_STATUS_NOTFOUND;
+}
- errno = 0; /* To distinguish success/failure after call */
- long val = strtol(name, &endptr, 10);
+/*
+enum nss_status
+_nss_rainbow_initgroups_dyn(const char *user, gid_t gid, long int *start, long int *size, gid_t **groupsp, long int limit, int *errnop) {
+ openlog("nss-rainbow", LOG_PID, LOG_LOCAL0);
- if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
- || (errno != 0 && val == 0)
- || (name == endptr)) {
- PERROR("Unable to parse name into a uid.");
- *errnop = (errno = 0) ? EINVAL : errno;
+ if (uid < 10000)
return NSS_STATUS_NOTFOUND;
- }
- return _nss_rainbow_getpwuid_r((uid_t)val, result, buf, buflen, errnop);
+ int pathlen = 1024;
+ char pathdata[1024], *pathbuf = pathdata;
+
+ result->pw_dir = buf;
+ CHK(format_buf(&pathbuf, &pathlen, "/home/olpc/isolation/1/uid_to_home_dir/%d", uid) == 1,
+ "Unable to calculate home dir.", out_error_errno);
+
+ struct stat st;
+ CHK(stat(result->pw_dir, &st) == -1,
+ "Stat failed for homebuf.", out_error_errno);
+ result->pw_uid = uid;
+ result->pw_gid = st.st_gid;
+
+ (*groupsp)[*start] =
+
+ return NSS_STATUS_SUCCESS;
+
+out_error_errno:
+ *ernnop = errno;
+ return NSS_STATUS_NOTFOUND;
+}
+enum nss_status _nss_rainbow_setgrent(void) {
+ openlog("nss-rainbow", LOG_PID, LOG_LOCAL0);
+ return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status _nss_rainbow_endgrent(void) {
+ openlog("nss-rainbow", LOG_PID, LOG_LOCAL0);
+ return NSS_STATUS_SUCCESS;
}
+
+struct group
+{
+ char *gr_name;
+ char *gr_passwd;
+ __gid_t gr_gid;
+ char **gr_mem;
+};
+enum nss_status
+_nss_rainbow_getgrent_r(struct group *result, char *buf, size_t buflen, int *errnop) {
+ openlog("nss-rainbow", LOG_PID, LOG_LOCAL0);
+ return NSS_STATUS_NOTFOUND;
+}
+
+enum nss_status
+_nss_rainbow_getgrgid_r(gid_t gid, struct group *gbuf, char *buf, size_t buflen, int *errnop) {
+ return NSS_STATUS_NOTFOUND;
+}
+
+enum nss_status
+_nss_rainbow_getgrnam_r(const char* name, struct group *gbuf, char *buf, size_t buflen, int *errnop) {
+ return NSS_STATUS_NOTFOUND;
+}
+
+*/
diff --git a/test_nat.c b/test_nat.c
new file mode 100644
index 0000000..d9468c9
--- /dev/null
+++ b/test_nat.c
@@ -0,0 +1,20 @@
+#include <errno.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+
+#include "cgen.h"
+#include "nat.h"
+
+int main()
+{
+ openlog("nat", LOG_PERROR, LOG_LOCAL0);
+ unsigned long data;
+ char buf[] = "12345";
+ CHK(parse_nat(&data, buf, strlen(buf)) == 1, "Death", out_death);
+ printf("%ld\n", data);
+ return 0;
+out_death:
+ printf("Death.");
+ return -1;
+}