diff options
author | Michael Stone <michael@laptop.org> | 2008-01-29 00:31:24 (GMT) |
---|---|---|
committer | Michael Stone <michael@laptop.org> | 2008-01-29 00:31:24 (GMT) |
commit | 2e8cf5ba5a2236a4d75ea994f1ed84177d062509 (patch) | |
tree | f98fd1dc8c5cc0e0d3173eee52f2100551d5f57a | |
parent | 5426c37456b3e12105ed46713e544d0aea81b392 (diff) |
Modularize.
-rw-r--r-- | Makefile | 40 | ||||
-rw-r--r-- | buf.c | 83 | ||||
-rw-r--r-- | buf.h | 2 | ||||
-rw-r--r-- | cgen.h | 7 | ||||
-rw-r--r-- | group.c | 56 | ||||
-rw-r--r-- | nat.c | 46 | ||||
-rw-r--r-- | nat.h | 3 | ||||
-rw-r--r-- | nss-rainbow.c | 179 | ||||
-rw-r--r-- | test_nat.c | 20 |
9 files changed, 330 insertions, 106 deletions
@@ -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 : @@ -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; +} @@ -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, ...); @@ -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;} @@ -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; +} +*/ @@ -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; +} @@ -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; +} |