From ef6b18c7bb36ae8be36ee3fe8777035578ceba54 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 01:40:18 -0500 Subject: [PATCH 01/40] Add ceod --- src/Makefile | 10 ++- src/daemon.h | 10 +++ src/dmaster.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++ src/dslave.c | 146 ++++++++++++++++++++++++++++++++++++++++ src/gss.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/gss.h | 11 +++ src/net.c | 141 ++++++++++++++++++++++++++++++++++++++ src/net.h | 45 +++++++++++++ src/ops.c | 110 ++++++++++++++++++++++++++++++ src/ops.h | 13 ++++ src/util.c | 127 +++++++++++++++++++++++++++++++++++ src/util.h | 17 ++++- 12 files changed, 984 insertions(+), 2 deletions(-) create mode 100644 src/daemon.h create mode 100644 src/dmaster.c create mode 100644 src/dslave.c create mode 100644 src/gss.c create mode 100644 src/gss.h create mode 100644 src/net.c create mode 100644 src/net.h create mode 100644 src/ops.c create mode 100644 src/ops.h diff --git a/src/Makefile b/src/Makefile index 6eab9be..4f07fc3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,7 +7,7 @@ override CFLAGS += -std=gnu99 $(INCLUDES) DESTDIR := PREFIX := /usr/local -BIN_PROGS := addmember addclub zfsaddhomedir +BIN_PROGS := addmember addclub zfsaddhomedir ceod EXT_PROGS := config-test LIBCEO_OBJECTS := common.o addhomedir.o @@ -19,6 +19,9 @@ LDAP_PROGS := addmember addclub KRB5_OBJECTS := krb5.o kadm.o KRB5_LDFLAGS := $(shell krb5-config --libs krb5 kadm-client) KRB5_PROGS := addmember addclub +NET_OBJECTS := net.o gss.o ops.o +NET_LDFLAGS := -lsctp $(shell krb5-config --libs gssapi) +NET_PROGS := ceod CONFIG_OBJECTS := config.o parser.o CONFIG_LDFLAGS := CONFIG_PROGS := $(OLDCEO_PROGS) $(LDAP_PROGS) $(KRB5_PROGS) $(NET_PROGS) @@ -30,6 +33,9 @@ all: $(BIN_PROGS) $(LIB_PROGS) $(EXT_PROGS) clean: rm -f $(ALL_PROGS) $(EXT_PROGS) *.o +ceod: dmaster.o dslave.o + $(CC) $(LDFLAGS) -o $@ $^ + config-test: config-test.o parser.o config.o: config.h config-vars.h @@ -38,6 +44,8 @@ install: install -d $(DESTDIR)$(PREFIX)/bin install addmember addclub $(DESTDIR)$(PREFIX)/bin +$(NET_PROGS): LDFLAGS += $(NET_LDFLAGS) +$(NET_PROGS): $(NET_OBJECTS) $(LIBCEO_PROGS): LDFLAGS += $(LIBCEO_LDFLAGS) $(LIBCEO_PROGS): $(LIBCEO_OBJECTS) $(LDAP_PROGS): LDFLAGS += $(LDAP_LDFLAGS) diff --git a/src/daemon.h b/src/daemon.h new file mode 100644 index 0000000..12bf804 --- /dev/null +++ b/src/daemon.h @@ -0,0 +1,10 @@ +/* dmain.c */ +extern int terminate; +extern int fatal_signal; + +/* dslave.c */ +void slave_main(int sock, struct sockaddr *addr); +void setup_slave(void); + +/* builtin-adduser.c */ +extern void builtin_adduser(struct sctp_meta *in, struct sctp_meta *out); diff --git a/src/dmaster.c b/src/dmaster.c new file mode 100644 index 0000000..d2d40f3 --- /dev/null +++ b/src/dmaster.c @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "net.h" +#include "config.h" +#include "gss.h" +#include "daemon.h" +#include "ldap.h" +#include "kadm.h" +#include "krb5.h" +#include "ops.h" + +static struct option opts[] = { + { "detach", 0, NULL, 'd' }, + { NULL, 0, NULL, '\0' }, +}; + +char *prog = NULL; + +int terminate = 0; +int fatal_signal; + +static int detach = 0; + +static void usage() { + fprintf(stderr, "Usage: %s [--detach]\n", prog); + exit(2); +} + +static void signal_handler(int sig) { + if (sig == SIGTERM || sig == SIGINT) { + const char *s = (sig == SIGTERM) ? "terminated" : "interrupt"; + notice("shutting down (%s)", s); + terminate = 1; + fatal_signal = sig; + signal(sig, SIG_DFL); + } else if (sig == SIGSEGV) { + error("segmentation fault"); + signal(sig, SIG_DFL); + raise(sig); + } else if (sig != SIGCHLD) { + fatal("unhandled signal %d", sig); + } +} + +static void setup_signals(void) { + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = signal_handler; + + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGSEGV, &sa, NULL); + + signal(SIGPIPE, SIG_IGN); + signal(SIGCHLD, SIG_IGN); +} + +static void setup_daemon(void) { + if (chdir("/")) + fatalpe("chdir('/')"); + if (detach) { + pid_t pid = fork(); + if (pid < 0) + fatalpe("fork"); + if (pid) + exit(0); + if (setsid() < 0) + fatalpe("setsid"); + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + } +} + +static void setup_auth(void) { + if (setenv("KRB5CCNAME", "MEMORY:ceod", 1)) + fatalpe("setenv"); + server_acquire_creds("ceod"); +} + +static void accept_one_client(int server) { + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + memset(&addr, 0, addrlen); + + int client = accept(server, (sa *)&addr, &addrlen); + if (client < 0) { + if (errno == EINTR) + return; + fatalpe("accept"); + } + + pid_t pid = fork(); + if (!pid) { + close(server); + slave_main(client, (sa *)&addr); + exit(0); + } + + close(client); +} + +static int master_main(void) { + int sock; + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(9987); + addr.sin_addr.s_addr = INADDR_ANY; + + sock = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + if (sock < 0) + fatalpe("socket"); + + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr))) + fatalpe("bind"); + + if (listen(sock, 128)) + fatalpe("listen"); + + setup_daemon(); + setup_fqdn(); + setup_signals(); + setup_auth(); + setup_ops(); + + notice("now accepting connections"); + + while (!terminate) + accept_one_client(sock); + + return 0; +} + +int main(int argc, char *argv[]) { + int opt; + + prog = basename(argv[0]); + init_log(prog, LOG_PID, LOG_DAEMON); + + configure(); + + while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) { + switch (opt) { + case 'd': + detach = 1; + break; + case '?': + usage(); + break; + default: + fatal("error parsing arguments"); + } + } + + if (argc != optind) + usage(); + + return master_main(); +} diff --git a/src/dslave.c b/src/dslave.c new file mode 100644 index 0000000..0001372 --- /dev/null +++ b/src/dslave.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "strbuf.h" +#include "net.h" +#include "config.h" +#include "gss.h" +#include "daemon.h" +#include "ldap.h" +#include "kadm.h" +#include "krb5.h" +#include "ops.h" + +static void signal_handler(int sig) { + if (sig == SIGSEGV) { + error("segmentation fault"); + signal(sig, SIG_DFL); + raise(sig); + } else if (sig != SIGCHLD) { + fatal("unhandled signal %d", sig); + } +} + +static void setup_slave_sigs(void) { + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = signal_handler; + + sigaction(SIGCHLD, &sa, NULL); + sigaction(SIGSEGV, &sa, NULL); + + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGPIPE, SIG_IGN); + + if (terminate) + raise(fatal_signal); +} + +static void setup_client(int client, struct sockaddr *addr) { + struct sctp_event_subscribe events; + memset(&events, 0, sizeof(events)); + events.sctp_data_io_event = 1; + events.sctp_address_event = 1; + events.sctp_send_failure_event = 1; + events.sctp_peer_error_event = 1; + events.sctp_partial_delivery_event = 1; + events.sctp_adaptation_layer_event = 1; + + if (setsockopt(client, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events))) + fatalpe("setsockopt(SCTP_EVENTS)"); +} + +static void handle_auth_message(struct strbuf *in, struct strbuf *out) { + gss_buffer_desc incoming_tok, outgoing_tok; + OM_uint32 maj_stat, min_stat; + + incoming_tok.value = in->buf; + incoming_tok.length = in->len; + + process_server_token(&incoming_tok, &outgoing_tok); + + strbuf_add(out, outgoing_tok.value, outgoing_tok.length); + + if (outgoing_tok.length) { + maj_stat = gss_release_buffer(&min_stat, &outgoing_tok); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_release_buffer", maj_stat, min_stat); + } +} + +static void handle_op_message(uint32_t in_type, struct strbuf *in, struct strbuf *out) { + struct op *op = get_local_op(in_type); + char *envp[16]; + + debug("running op: %s", op->name); + + if (!op->name) + fatal("operation %x does not exist", in_type); + + make_env(envp, "LANG", "C", "CEO_USER", client_username(), + "CEO_CONFIG_DIR", config_dir, NULL); + char *argv[] = { op->path, NULL, }; + + if (spawnvem(op->path, argv, envp, in, out, 0)) + fatal("child %s failed", op->path); + + free_env(envp); +} + +static void handle_one_message(int sock, struct sctp_meta *in_meta, struct strbuf *in) { + struct strbuf out = STRBUF_INIT; + uint32_t ppid = in_meta->sinfo.sinfo_ppid; + + if (ppid == MSG_AUTH) + handle_auth_message(in, &out); + else + handle_op_message(ppid, in, &out); + + if (out.len && sctp_sendmsg(sock, out.buf, out.len, + (sa *)&in_meta->from, in_meta->fromlen, ppid, + 0, 0, 0, 0) < 0) + fatalpe("sctp_sendmsg"); + + strbuf_release(&out); +} + +void slave_main(int sock, struct sockaddr *addr) { + char addrstr[INET_ADDRSTRLEN]; + struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; + struct sctp_meta msg_meta; + struct strbuf msg = STRBUF_INIT; + + if (addr->sa_family != AF_INET) + fatal("unsupported address family %d", addr->sa_family); + + if (!inet_ntop(AF_INET, &addr_in->sin_addr, addrstr, sizeof(addrstr))) + fatalpe("inet_ntop"); + + notice("accepted connection from %s", addrstr); + + setup_slave_sigs(); + setup_client(sock, addr); + + while (!terminate) { + if (!receive_one_message(sock, &msg_meta, &msg)) + break; + handle_one_message(sock, &msg_meta, &msg); + } + + notice("connection closed by peer %s", addrstr); + + strbuf_release(&msg); +} + diff --git a/src/gss.c b/src/gss.c new file mode 100644 index 0000000..9305ce6 --- /dev/null +++ b/src/gss.c @@ -0,0 +1,183 @@ +#include +#include +#include +#include + +#include "util.h" +#include "gss.h" +#include "net.h" +#include "strbuf.h" + +static gss_cred_id_t my_creds = GSS_C_NO_CREDENTIAL; +static gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT; +static gss_name_t peer_name = GSS_C_NO_NAME; +static gss_name_t imported_service = GSS_C_NO_NAME; +static gss_OID mech_type = GSS_C_NO_OID; +static gss_buffer_desc peer_principal; +static char *peer_username; +static OM_uint32 ret_flags; +static int complete; +char service_name[128]; + +static void display_status(char *prefix, OM_uint32 code, int type) { + OM_uint32 maj_stat, min_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx = 0; + + maj_stat = gss_display_status(&min_stat, code, type, GSS_C_NULL_OID, + &msg_ctx, &msg); + logmsg(LOG_ERR, "%s: %s", prefix, (char *)msg.value); + gss_release_buffer(&min_stat, &msg); + + while (msg_ctx) { + maj_stat = gss_display_status(&min_stat, code, type, GSS_C_NULL_OID, + &msg_ctx, &msg); + logmsg(LOG_ERR, "additional: %s", (char *)msg.value); + gss_release_buffer(&min_stat, &msg); + } +} + +void gss_fatal(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat) { + logmsg(LOG_ERR, "fatal: %s", msg); + display_status("major", maj_stat, GSS_C_GSS_CODE); + display_status("minor", min_stat, GSS_C_MECH_CODE); + exit(1); +} + +static void import_service(const char *service, const char *hostname) { + OM_uint32 maj_stat, min_stat; + gss_buffer_desc buf_desc; + + if (snprintf(service_name, sizeof(service_name), + "%s@%s", service, hostname) >= sizeof(service_name)) + fatal("service name too long"); + + buf_desc.value = service_name; + buf_desc.length = strlen(service_name); + + maj_stat = gss_import_name(&min_stat, &buf_desc, + GSS_C_NT_HOSTBASED_SERVICE, &imported_service); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_import_name", maj_stat, min_stat); +} + +static void check_services(OM_uint32 flags) { + debug("gss services: %sconf %sinteg %smutual %sreplay %ssequence", + flags & GSS_C_CONF_FLAG ? "+" : "-", + flags & GSS_C_INTEG_FLAG ? "+" : "-", + flags & GSS_C_MUTUAL_FLAG ? "+" : "-", + flags & GSS_C_REPLAY_FLAG ? "+" : "-", + flags & GSS_C_SEQUENCE_FLAG ? "+" : "-"); + if (~flags & GSS_C_CONF_FLAG) + fatal("confidentiality service required"); + if (~flags & GSS_C_INTEG_FLAG) + fatal("integrity service required"); + if (~flags & GSS_C_MUTUAL_FLAG) + fatal("mutual authentication required"); +} + +void server_acquire_creds(const char *service) { + OM_uint32 maj_stat, min_stat; + OM_uint32 time_rec; + + if (!strlen(fqdn.buf)) + fatal("empty fqdn"); + + import_service(service, fqdn.buf); + + notice("acquiring credentials for %s", service_name); + + maj_stat = gss_acquire_cred(&min_stat, imported_service, GSS_C_INDEFINITE, + GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &my_creds, + NULL, &time_rec); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_acquire_cred", maj_stat, min_stat); + + if (time_rec != GSS_C_INDEFINITE) + fatal("credentials valid for %d seconds (oops)", time_rec); +} + +void client_acquire_creds(const char *service, const char *hostname) { + import_service(service, hostname); +} + +int process_server_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok) { + OM_uint32 maj_stat, min_stat; + OM_uint32 time_rec; + gss_OID name_type; + + if (complete) + fatal("unexpected %zd-byte token from peer", incoming_tok->length); + + maj_stat = gss_accept_sec_context(&min_stat, &context_handle, my_creds, + incoming_tok, GSS_C_NO_CHANNEL_BINDINGS, &peer_name, &mech_type, + outgoing_tok, &ret_flags, &time_rec, NULL); + if (maj_stat == GSS_S_COMPLETE) { + check_services(ret_flags); + + complete = 1; + + maj_stat = gss_display_name(&min_stat, peer_name, &peer_principal, &name_type); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_display_name", maj_stat, min_stat); + + notice("client authenticated as %s", (char *)peer_principal.value); + debug("context expires in %d seconds",time_rec); + + } else if (maj_stat != GSS_S_CONTINUE_NEEDED) { + gss_fatal("gss_accept_sec_context", maj_stat, min_stat); + } + + return complete; +} + +int process_client_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok) { + OM_uint32 maj_stat, min_stat; + OM_uint32 time_rec; + gss_OID_desc krb5 = *gss_mech_krb5; + + if (complete) + fatal("unexpected token from peer"); + + maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &context_handle, + imported_service, &krb5, GSS_C_MUTUAL_FLAG | + GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG, + GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, + incoming_tok, NULL, outgoing_tok, &ret_flags, + &time_rec); + if (maj_stat == GSS_S_COMPLETE) { + notice("server authenticated as %s", service_name); + notice("context expires in %d seconds", time_rec); + + check_services(ret_flags); + + complete = 1; + + } else if (maj_stat != GSS_S_CONTINUE_NEEDED) { + gss_fatal("gss_init_sec_context", maj_stat, min_stat); + } + + return complete; +} + +int initial_client_token(gss_buffer_t outgoing_tok) { + return process_client_token(GSS_C_NO_BUFFER, outgoing_tok); +} + +char *client_principal(void) { + return complete ? (char *)peer_principal.value : NULL; +} + +char *client_username(void) { + if (!peer_username) { + char *princ = client_principal(); + if (princ) { + peer_username = xstrdup(princ); + char *c = strchr(peer_username, '@'); + if (c) + *c = '\0'; + } + } + return peer_username; +} + diff --git a/src/gss.h b/src/gss.h new file mode 100644 index 0000000..7e7c290 --- /dev/null +++ b/src/gss.h @@ -0,0 +1,11 @@ +#include +#include + +void server_acquire_creds(const char *service); +void client_acquire_creds(const char *service, const char *hostname); +void gss_fatal(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat); +int process_server_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok); +int process_client_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok); +int initial_client_token(gss_buffer_t outgoing_tok); +char *client_principal(void); +char *client_username(void); diff --git a/src/net.c b/src/net.c new file mode 100644 index 0000000..825c917 --- /dev/null +++ b/src/net.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include + +#include "util.h" +#include "net.h" +#include "gss.h" +#include "strbuf.h" + +struct strbuf fqdn = STRBUF_INIT; + +const size_t MAX_MSGLEN = 65536; +const size_t MSG_BUFINC = 4096; + +void setup_fqdn(void) { + struct utsname uts; + struct hostent *lo; + + if (uname(&uts)) + fatalpe("uname"); + lo = gethostbyname(uts.nodename); + if (!lo) + fatalpe("gethostbyname"); + + strbuf_addstr(&fqdn, lo->h_name); +} + +static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg, int *notification) { + size_t len = 0; + int flags; + int bytes; + + strbuf_reset(msg); + + do { + msg_meta->fromlen = sizeof(msg_meta->from); + + bytes = sctp_recvmsg(sock, msg->buf + len, strbuf_avail(msg) - len, + (sa *)&msg_meta->from, &msg_meta->fromlen, &msg_meta->sinfo, &flags); + + if (bytes < 0) + fatalpe("sctp_recvmsg"); + if (!bytes) + break; + len += bytes; + + if (msg->len > MAX_MSGLEN) + fatal("oversized message received"); + if (strbuf_avail(msg) < MSG_BUFINC) + strbuf_grow(msg, MSG_BUFINC); + + } while (~flags & MSG_EOR); + + if (!bytes && len) + fatalpe("EOF in the middle of a message"); + + *notification = flags & MSG_NOTIFICATION; + if (*notification) + notification_dbg(msg->buf); + + strbuf_setlen(msg, len); + return len; +} + +int receive_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg) { + int notification = 0; + + do { + recv_one_message(sock, msg_meta, msg, ¬ification); + } while (notification); + + return msg->len > 0; +} + +void notification_dbg(char *notification) { + union sctp_notification *sn = (union sctp_notification *) notification; + char *extra; + + switch (sn->sn_header.sn_type) { + case SCTP_ASSOC_CHANGE: + extra = "unknown state"; + switch (sn->sn_assoc_change.sac_state) { + case SCTP_COMM_UP: extra = "established"; break; + case SCTP_COMM_LOST: extra = "lost"; break; + case SCTP_RESTART: extra = "restarted"; break; + case SCTP_SHUTDOWN_COMP: extra = "completed shutdown"; break; + case SCTP_CANT_STR_ASSOC: extra = "cannot start"; break; + } + debug("association changed: association 0x%x %s", sn->sn_assoc_change.sac_assoc_id, extra); + break; + case SCTP_PEER_ADDR_CHANGE: + extra = "unknown state"; + switch (sn->sn_paddr_change.spc_state) { + case SCTP_ADDR_AVAILABLE: extra = "unavailable"; break; + case SCTP_ADDR_UNREACHABLE: extra = "unreachable"; break; + case SCTP_ADDR_REMOVED: extra = "removed"; break; + case SCTP_ADDR_ADDED: extra = "added"; break; + case SCTP_ADDR_MADE_PRIM: extra = "made primary"; break; +#ifdef SCTP_ADDR_CONFIRMED + case SCTP_ADDR_CONFIRMED: extra = "confirmed"; break; +#endif + } + + struct sockaddr_in *sa = (struct sockaddr_in *) &sn->sn_paddr_change.spc_aaddr; + char addr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &sa->sin_addr, addr, sizeof(addr)); + debug("peer address change: remote address %s %s", addr, extra); + break; + case SCTP_REMOTE_ERROR: + debug("remote error: association=0x%x error=0x%x", + sn->sn_remote_error.sre_assoc_id, + sn->sn_remote_error.sre_error); + break; + case SCTP_SEND_FAILED: + debug("send failed: association=0x%x error=0x%x", + sn->sn_send_failed.ssf_assoc_id, + sn->sn_send_failed.ssf_error); + break; + case SCTP_ADAPTATION_INDICATION: + debug("adaptation indication: 0x%x", + sn->sn_adaptation_event.sai_adaptation_ind); + break; + case SCTP_PARTIAL_DELIVERY_EVENT: + extra = "unknown indication"; + switch (sn->sn_pdapi_event.pdapi_indication) { + case SCTP_PARTIAL_DELIVERY_ABORTED: + extra = "partial delivery aborted"; + break; + } + debug("partial delivery event: %s", extra); + break; + case SCTP_SHUTDOWN_EVENT: + debug("association 0x%x was shut down", + sn->sn_shutdown_event.sse_assoc_id); + break; + default: + debug("unknown sctp notification type 0x%x\n", + sn->sn_header.sn_type); + } +} diff --git a/src/net.h b/src/net.h new file mode 100644 index 0000000..0e6ac9f --- /dev/null +++ b/src/net.h @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include + +#if ! defined(SCTP_ADDR_CONFIRMED) && defined(__linux__) +#define SCTP_ADDR_CONFIRMED 5 +#endif + +void notification_dbg(char *); + +#ifdef SCTP_ADAPTION_LAYER +#define sctp_adaptation_layer_event sctp_adaption_layer_event +#define sn_adaptation_event sn_adaption_event +#define sai_adaptation_ind sai_adaption_ind +#define SCTP_ADAPTATION_INDICATION SCTP_ADAPTION_INDICATION +#endif + +typedef struct sockaddr sa; + +extern struct strbuf fqdn; +extern void setup_fqdn(void); + +struct sctp_meta { + struct sockaddr_storage from; + socklen_t fromlen; + struct sctp_sndrcvinfo sinfo; +}; + +enum { + MSG_AUTH = 0x8000000, + MSG_EXPLODE = 0x8000001, +}; + +#ifdef MSG_ABORT +#define SCTP_ABORT MSG_ABORT +#define SCTP_EOF MSG_EOF +#endif + +#define EKERB -2 +#define ELDAP -3 + +int receive_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg); diff --git a/src/ops.c b/src/ops.c new file mode 100644 index 0000000..9cf53c3 --- /dev/null +++ b/src/ops.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include + +#include "strbuf.h" +#include "ops.h" +#include "net.h" +#include "util.h" +#include "config.h" + +static struct op *ops; + +static const char *default_op_dir = "/usr/lib/ceod"; +static const char *op_dir; + +static void add_op(char *host, char *name, uint32_t id) { + struct op *new = xmalloc(sizeof(struct op)); + errno = 0; + new->next = ops; + new->name = xstrdup(name); + new->id = id; + new->path = NULL; + + struct hostent *hostent = gethostbyname(host); + if (!hostent) + badconf("cannot add op %s: %s: %s", name, host, hstrerror(h_errno)); + new->hostname = strdup(hostent->h_name); + new->local = !strcmp(fqdn.buf, hostent->h_name); + new->addr = *(struct in_addr *)hostent->h_addr_list[0]; + + if (new->local) { + new->path = xmalloc(strlen(op_dir) + strlen("/op-") + strlen(name) + 1); + sprintf(new->path, "%s/op-%s", op_dir, name); + if (access(new->path, X_OK)) + fatalpe("cannot add op: %s: %s", name, new->path); + } + + ops = new; + debug("added op %s (%s%s)", new->name, new->local ? "" : "on ", + new->local ? "local" : host); +} + +struct op *get_local_op(uint32_t id) { + for (struct op *op = ops; op; op = op->next) { + if (op->local && op->id == id) + return op; + } + return NULL; +} + +struct op *find_op(const char *name) { + for (struct op *op = ops; op; op = op->next) { + if (!strcmp(name, op->name)) + return op; + } + return NULL; +} + +void setup_ops(void) { + char op_config_dir[1024]; + DIR *dp; + struct dirent *de; + struct strbuf line = STRBUF_INIT; + unsigned lineno = 0; + unsigned op_count = 0; + + op_dir = getenv("CEO_LIB_DIR") ?: default_op_dir; + + if (snprintf(op_config_dir, sizeof(op_config_dir), "%s/%s", config_dir, "ops.d") >= sizeof(op_config_dir)) + fatal("ops dir path too long"); + + dp = opendir(op_config_dir); + if (!dp) + fatalpe("opendir: %s", op_config_dir); + + while ((de = readdir(dp))) { + FILE *fp = fopenat(dp, de->d_name, O_RDONLY); + if (!fp) + warnpe("open: %s/%s", op_config_dir, de->d_name); + while (strbuf_getline(&line, fp, '\n') != EOF) { + lineno++; + strbuf_trim(&line); + + if (!line.len || line.buf[0] == '#') + continue; + + struct strbuf **words = strbuf_splitws(&line); + + if (strbuf_list_len(words) != 3) + badconf("%s/%s: expected three words on line %d", op_config_dir, de->d_name, lineno); + + errno = 0; + char *end; + int id = strtol(words[2]->buf, &end, 0); + if (errno || *end) + badconf("%s/%s: invalid id '%s' on line %d", op_config_dir, de->d_name, words[2]->buf, lineno); + + add_op(words[0]->buf, words[1]->buf, id); + op_count++; + + strbuf_list_free(words); + } + } + + closedir(dp); + strbuf_release(&line); +} + diff --git a/src/ops.h b/src/ops.h new file mode 100644 index 0000000..21ee45a --- /dev/null +++ b/src/ops.h @@ -0,0 +1,13 @@ +struct op { + char *name; + uint32_t id; + int local; + char *hostname; + char *path; + struct in_addr addr; + struct op *next; +}; + +void setup_ops(void); +struct op *find_op(const char *name); +struct op *get_local_op(uint32_t id); diff --git a/src/util.c b/src/util.c index 656b587..3078d23 100644 --- a/src/util.c +++ b/src/util.c @@ -1,10 +1,13 @@ +#define _ATFILE_SOURCE #include #include #include #include #include +#include #include #include +#include #include "util.h" #include "strbuf.h" @@ -148,3 +151,127 @@ int spawnv(const char *path, char *const argv[]) { exit(execv(path, argv)); return status; } + +void full_write(int fd, const void *buf, size_t count) { + ssize_t total = 0; + + while (total < count) { + ssize_t wcount = write(fd, (char *)buf + total, count - total); + if (wcount < 0) + fatalpe("write"); + total += wcount; + } +} + +int spawnvem(const char *path, char *const *argv, char *const *envp, const struct strbuf *output, struct strbuf *input, int cap_stderr) { + int pid, wpid, status; + int tochild[2]; + int fmchild[2]; + + if (pipe(tochild)) + fatalpe("pipe"); + if (pipe(fmchild)) + fatalpe("pipe"); + + fflush(stdout); + fflush(stderr); + + pid = fork(); + if (pid < 0) + fatalpe("fork"); + if (!pid) { + dup2(tochild[0], STDIN_FILENO); + dup2(fmchild[1], STDOUT_FILENO); + if (cap_stderr) + dup2(STDOUT_FILENO, STDERR_FILENO); + close(tochild[0]); + close(tochild[1]); + close(fmchild[0]); + close(fmchild[1]); + execve(path, argv, envp); + fatalpe("execve"); + } else { + close(tochild[0]); + close(fmchild[1]); + full_write(tochild[1], output->buf, output->len); + close(tochild[1]); + + if (input) + strbuf_read(input, fmchild[0], 0); + close(fmchild[0]); + } + + wpid = waitpid(pid, &status, 0); + if (wpid < 0) + fatalpe("waitpid"); + else if (wpid != pid) + fatal("waitpid is broken"); + + if (WIFEXITED(status) && WEXITSTATUS(status)) + notice("child %s exited with status %d", path, WEXITSTATUS(status)); + else if (WIFSIGNALED(status)) + notice("child %s killed by signal %d", path, WTERMSIG(status)); + + return status; +} + +int spawnv_msg(const char *path, char *const *argv, const struct strbuf *output) { + return spawnvem(path, argv, environ, output, NULL, 0); +} + +int check_group(char *username, char *group) { + struct group *grp = getgrnam(group); + char **members; + + if (grp) + for (members = grp->gr_mem; *members; members++) + if (!strcmp(username, *members)) + return 1; + + return 0; +} + +FILE *fopenat(DIR *d, const char *path, int flags) { + int dfd = dirfd(d); + if (dfd < 0) + return NULL; + int fd = openat(dfd, path, flags); + if (fd < 0) + return NULL; + return fdopen(fd, flags & O_RDWR ? "r+" : + flags & O_WRONLY ? "w" : + "r"); +} + +void make_env(char **envp, ...) { + const size_t len = 4096; + size_t used = 0; + int args = 0; + char *buf = xmalloc(len); + va_list ap; + va_start(ap, envp); + char *name, *val; + + while ((name = va_arg(ap, char *))) { + val = va_arg(ap, char *); + if (!val) + continue; + int n = snprintf(buf + used, len - used, "%s=%s", name, val); + if (n < 0) + fatalpe("snprintf"); + if (n >= len - used) + fatal("environment too big"); + + envp[args++] = buf + used; + used += n + 1; + } + + if (!args) + free(buf); + + envp[args] = NULL; +} + +void free_env(char **envp) { + free(*envp); +} diff --git a/src/util.h b/src/util.h index 5d2757f..70fc82d 100644 --- a/src/util.h +++ b/src/util.h @@ -2,8 +2,14 @@ #define CEO_UTIL_H #include +#include #include #include +#include +#include +#include + +#include "strbuf.h" #ifdef __GNUC__ #define NORETURN __attribute__((__noreturn__)) @@ -17,8 +23,18 @@ #define LOG_AUTHPRIV LOG_AUTH #endif +extern char **environ; + int spawnv(const char *path, char *const *argv); +int spawnv_msg(const char *path, char *const *argv, const struct strbuf *output); +int spawnvem(const char *path, char *const *argv, char *const *envp, const struct strbuf *output, struct strbuf *input, int cap_stderr); +void full_write(int fd, const void *buf, size_t count); +ssize_t full_read(int fd, void *buf, size_t len); +FILE *fopenat(DIR *d, const char *path, int flags); +void make_env(char **envp, ...); +void free_env(char **envp); void init_log(const char *ident, int option, int facility); +int check_group(char *username, char *group); PRINTF_LIKE(0) NORETURN void fatal(const char *, ...); PRINTF_LIKE(0) NORETURN void fatalpe(const char *, ...); @@ -59,7 +75,6 @@ static inline void *xcalloc(size_t nmemb, size_t size) { return alloc; } - static inline char *xstrdup(const char *s) { char *dup = strdup(s); From 57b6e1247682f71de40a9a50cff665c700a3bf8d Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 01:41:42 -0500 Subject: [PATCH 02/40] Add ceoc --- src/Makefile | 3 +- src/ceoc.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 src/ceoc.c diff --git a/src/Makefile b/src/Makefile index 4f07fc3..d5ac050 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,6 +8,7 @@ DESTDIR := PREFIX := /usr/local BIN_PROGS := addmember addclub zfsaddhomedir ceod +LIB_PROGS := ceoc EXT_PROGS := config-test LIBCEO_OBJECTS := common.o addhomedir.o @@ -21,7 +22,7 @@ KRB5_LDFLAGS := $(shell krb5-config --libs krb5 kadm-client) KRB5_PROGS := addmember addclub NET_OBJECTS := net.o gss.o ops.o NET_LDFLAGS := -lsctp $(shell krb5-config --libs gssapi) -NET_PROGS := ceod +NET_PROGS := ceod ceoc CONFIG_OBJECTS := config.o parser.o CONFIG_LDFLAGS := CONFIG_PROGS := $(OLDCEO_PROGS) $(LDAP_PROGS) $(KRB5_PROGS) $(NET_PROGS) diff --git a/src/ceoc.c b/src/ceoc.c new file mode 100644 index 0000000..a4899f7 --- /dev/null +++ b/src/ceoc.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include + +#include "util.h" +#include "net.h" +#include "gss.h" +#include "ops.h" +#include "config.h" + +char *prog = NULL; + +static struct option opts[] = { + { NULL, 0, NULL, '\0' }, +}; + +static void usage() { + fprintf(stderr, "Usage: %s op\n", prog); + exit(2); +} + +static void send_gss_token(int sock, struct sockaddr *addr, socklen_t addrlen, gss_buffer_t token) { + OM_uint32 maj_stat, min_stat; + + if (sctp_sendmsg(sock, token->value, token->length, + addr, addrlen, MSG_AUTH, 0, 0, 0, 0) < 0) + fatalpe("sctp_sendmsg"); + + maj_stat = gss_release_buffer(&min_stat, token); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_release_buffer", maj_stat, min_stat); +} + +static void client_gss_auth(int sock, struct sockaddr *addr, socklen_t addrlen) { + gss_buffer_desc incoming_tok, outgoing_tok; + struct sctp_meta msg_meta; + struct strbuf msg = STRBUF_INIT; + int complete; + + complete = initial_client_token(&outgoing_tok); + + for (;;) { + if (outgoing_tok.length) + send_gss_token(sock, addr, addrlen, &outgoing_tok); + else if (!complete) + fatal("no token to send during auth"); + + if (complete) + break; + + if (!receive_one_message(sock, &msg_meta, &msg)) + fatal("connection closed during auth"); + + if (msg_meta.sinfo.sinfo_ppid != MSG_AUTH) + fatal("unexpected message type 0x%x", msg_meta.sinfo.sinfo_ppid); + + incoming_tok.value = msg.buf; + incoming_tok.length = msg.len; + + complete = process_client_token(&incoming_tok, &outgoing_tok); + } + + strbuf_release(&msg); +} + +void run_remote(struct op *op, struct strbuf *in, struct strbuf *out) { + const char *hostname = op->hostname; + int sock = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); + struct sockaddr_in addr; + struct sctp_meta response_meta; + + if (!in->len) + fatal("no data to send"); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(9987); + addr.sin_addr = op->addr; + + struct sctp_event_subscribe events; + memset(&events, 0, sizeof(events)); + events.sctp_data_io_event = 1; + events.sctp_association_event = 1; + events.sctp_address_event = 1; + events.sctp_send_failure_event = 1; + events.sctp_peer_error_event = 1; + events.sctp_shutdown_event = 1; + events.sctp_partial_delivery_event = 1; + events.sctp_adaptation_layer_event = 1; + + if (setsockopt(sock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events))) + fatalpe("setsockopt"); + + client_acquire_creds("ceod", hostname); + client_gss_auth(sock, (sa *)&addr, sizeof(addr)); + + if (sctp_sendmsg(sock, in->buf, in->len, (struct sockaddr *)&addr, + sizeof(addr), op->id, 0, 0, 0, 0) < 0) + fatalpe("sctp_sendmsg"); + + if (!receive_one_message(sock, &response_meta, out)) + fatal("no response received for op %s", op->name); + + if (response_meta.sinfo.sinfo_ppid != op->id) + fatal("wrong ppid from server: expected %d got %d", op->id, response_meta.sinfo.sinfo_ppid); + + if (sctp_sendmsg(sock, NULL, 0, (struct sockaddr *)&addr, + sizeof(addr), 0, SCTP_EOF, 0, 0 ,0) < 0) + fatalpe("sctp_sendmsg"); +} + +int client_main(char *op_name) { + struct op *op = find_op(op_name); + + if (!op) + fatal("no such op: %s", op_name); + + struct strbuf in = STRBUF_INIT; + struct strbuf out = STRBUF_INIT; + + if (strbuf_read(&in, STDIN_FILENO, 0) < 0) + fatalpe("read"); + + run_remote(op, &in, &out); + + if (strbuf_write(&out, STDOUT_FILENO) < 0) + fatalpe("write"); + + strbuf_release(&in); + strbuf_release(&out); + + return 0; +} + +int main(int argc, char *argv[]) { + int opt; + char *op; + + prog = basename(argv[0]); + init_log(prog, 0, LOG_USER); + + configure(); + setup_ops(); + + while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) { + switch (opt) { + case '?': + usage(); + break; + default: + fatal("error parsing arguments"); + } + } + + if (argc - optind != 1) + usage(); + + op = argv[optind++]; + + return client_main(op); +} From 0edfa120eb49003f07d384e9de933b7d8f45d00d Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 01:46:30 -0500 Subject: [PATCH 03/40] Add op-adduser --- src/Makefile | 18 ++- src/ceo.proto | 23 ++++ src/op-adduser.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 320 insertions(+), 4 deletions(-) create mode 100644 src/ceo.proto create mode 100644 src/op-adduser.c diff --git a/src/Makefile b/src/Makefile index d5ac050..f1d94bb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,7 +8,7 @@ DESTDIR := PREFIX := /usr/local BIN_PROGS := addmember addclub zfsaddhomedir ceod -LIB_PROGS := ceoc +LIB_PROGS := ceoc op-adduser EXT_PROGS := config-test LIBCEO_OBJECTS := common.o addhomedir.o @@ -16,13 +16,16 @@ LIBCEO_LDFLAGS := LIBCEO_PROGS := addmember addclub LDAP_OBJECTS := ldap.o LDAP_LDFLAGS := -lldap -LDAP_PROGS := addmember addclub +LDAP_PROGS := addmember addclub op-adduser KRB5_OBJECTS := krb5.o kadm.o KRB5_LDFLAGS := $(shell krb5-config --libs krb5 kadm-client) -KRB5_PROGS := addmember addclub +KRB5_PROGS := addmember addclub op-adduser NET_OBJECTS := net.o gss.o ops.o NET_LDFLAGS := -lsctp $(shell krb5-config --libs gssapi) NET_PROGS := ceod ceoc +PROTO_OBJECTS := ceo.pb-c.o +PROTO_LDFLAGS := -lprotobuf-c +PROTO_PROGS := op-adduser CONFIG_OBJECTS := config.o parser.o CONFIG_LDFLAGS := CONFIG_PROGS := $(OLDCEO_PROGS) $(LDAP_PROGS) $(KRB5_PROGS) $(NET_PROGS) @@ -32,7 +35,12 @@ UTIL_PROGS := config-test zfsaddhomedir $(CONFIG_PROGS) all: $(BIN_PROGS) $(LIB_PROGS) $(EXT_PROGS) clean: - rm -f $(ALL_PROGS) $(EXT_PROGS) *.o + rm -f $(ALL_PROGS) $(EXT_PROGS) *.o ceo.pb-c.c ceo.pb-c.h + +op-adduser.o addmember.o addclub.o: ceo.pb-c.h + +ceo.pb-c.c ceo.pb-c.h: ceo.proto + protoc-c --c_out=. ceo.proto ceod: dmaster.o dslave.o $(CC) $(LDFLAGS) -o $@ $^ @@ -53,6 +61,8 @@ $(LDAP_PROGS): LDFLAGS += $(LDAP_LDFLAGS) $(LDAP_PROGS): $(LDAP_OBJECTS) $(KRB5_PROGS): LDFLAGS += $(KRB5_LDFLAGS) $(KRB5_PROGS): $(KRB5_OBJECTS) +$(PROTO_PROGS): LDFLAGS += $(PROTO_LDFLAGS) +$(PROTO_PROGS): $(PROTO_OBJECTS) $(CONFIG_PROGS): LDFLAGS += $(CONFIG_LDFLAGS) $(CONFIG_PROGS): $(CONFIG_OBJECTS) $(UTIL_PROGS): LDFLAGS += $(UTIL_LDFLAGS) diff --git a/src/ceo.proto b/src/ceo.proto new file mode 100644 index 0000000..386bc77 --- /dev/null +++ b/src/ceo.proto @@ -0,0 +1,23 @@ +package ceo; + +message StatusMessage { + required int32 status = 1; + required string message = 2; +} + +message AddUser { + enum Type { + MEMBER = 1; + CLUB = 2; + } + + required Type type = 1; + required string username = 2; + optional string password = 3; + optional string realname = 4; + optional string program = 5; +} + +message AddUserResponse { + repeated StatusMessage messages = 1; +} diff --git a/src/op-adduser.c b/src/op-adduser.c new file mode 100644 index 0000000..5e1990e --- /dev/null +++ b/src/op-adduser.c @@ -0,0 +1,283 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "net.h" +#include "ceo.pb-c.h" +#include "config.h" +#include "gss.h" +#include "krb5.h" +#include "ldap.h" +#include "kadm.h" +#include "daemon.h" +#include "strbuf.h" + +char *prog; + +static const int MAX_MESSAGES = 32; +static const int MAX_MESGSIZE = 512; + +char *user_types[] = { + [CEO__ADD_USER__TYPE__MEMBER] = "member", + [CEO__ADD_USER__TYPE__CLUB] = "club", +}; + +Ceo__AddUserResponse *response_create(void) { + Ceo__AddUserResponse *r = xmalloc(sizeof(Ceo__AddUserResponse)); + ceo__add_user_response__init(r); + r->n_messages = 0; + r->messages = xmalloc(MAX_MESSAGES * sizeof(Ceo__StatusMessage *)); + return r; +} + +int32_t response_message(Ceo__AddUserResponse *r, int32_t status, char *fmt, ...) { + va_list args; + Ceo__StatusMessage *statusmsg = xmalloc(sizeof(Ceo__StatusMessage)); + char *message = xmalloc(MAX_MESGSIZE); + + va_start(args, fmt); + vsnprintf(message, MAX_MESGSIZE, fmt, args); + va_end(args); + + ceo__status_message__init(statusmsg); + statusmsg->status = status; + statusmsg->message = message; + + if (r->n_messages >= MAX_MESSAGES) + fatal("too many messages"); + r->messages[r->n_messages++] = statusmsg; + + if (status) + error("%s", message); + else + notice("%s", message); + + return status; +} + +void response_delete(Ceo__AddUserResponse *r) { + int i; + + for (i = 0; i < r->n_messages; i++) { + free(r->messages[i]->message); + free(r->messages[i]); + } + free(r->messages); + free(r); +} + + +static int check_adduser(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *client) { + int office = check_group(client, "office"); + int syscom = check_group(client, "syscom"); + + notice("adding uid=%s cn=%s by %s", in->username, in->realname, client); + + if (!office && !syscom) + return response_message(out, EPERM, "%s not authorized to create users", client); + + if (!in->username) + return response_message(out, EINVAL, "missing required argument: username"); + if (!in->realname) + return response_message(out, EINVAL, "missing required argument: realname"); + + if (in->type == CEO__ADD_USER__TYPE__MEMBER) { + if (!in->password) + return response_message(out, EINVAL, "missing required argument: password"); + } else if (in->type == CEO__ADD_USER__TYPE__CLUB) { + if (in->password) + return response_message(out, EINVAL, "club accounts cannot have passwords"); + if (in->program) + return response_message(out, EINVAL, "club accounts cannot have programs"); + } else { + return response_message(out, EINVAL, "invalid user type: %d", in->type); + } + + if (getpwnam(in->username) != NULL) + return response_message(out, EEXIST, "user %s already exists", in->username); + + if (getgrnam(in->username) != NULL) + return response_message(out, EEXIST, "group %s already exists", in->username); + + if (ceo_user_exists(in->username)) + return response_message(out, EEXIST, "user %s already exists in LDAP", in->username); + + if (ceo_group_exists(in->username)) + return response_message(out, EEXIST, "group %s already exists in LDAP", in->username); + + return 0; +} + +static void adduser_spam(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *client, char *prog, int status) { + char *argv[] = { + notify_hook, prog, client, + in->username, in->realname, in->program ?: "", + status ? "failure" : "success", NULL + }; + + struct strbuf message = STRBUF_INIT; + for (int i = 0; i < out->n_messages; i++) + strbuf_addf(&message, "%s\n", out->messages[i]->message); + + spawnv_msg(notify_hook, argv, &message); + strbuf_release(&message); +} + +static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) { + char homedir[1024]; + int user_stat, group_stat, krb_stat; + int id; + + if (snprintf(homedir, sizeof(homedir), "%s/%s", + member_home, in->username) >= sizeof(homedir)) + fatal("homedir overflow"); + + if ((id = ceo_new_uid(member_min_id, member_max_id)) <= 0) + fatal("no available uids in range [%ld, %ld]", member_min_id, member_max_id); + + if ((krb_stat = ceo_del_princ(in->username))) + return response_message(out, EEXIST, "unable to overwrite orphaned kerberos principal %s", in->username); + + if ((krb_stat = ceo_add_princ(in->username, in->password))) + return response_message(out, EKERB, "unable to create kerberos principal %s", in->username); + response_message(out, 0, "successfully created principal"); + + if ((user_stat = ceo_add_user(in->username, users_base, "member", in->realname, homedir, + member_shell, id, "program", in->program, NULL))) + return response_message(out, ELDAP, "unable to create ldap account %s", in->username); + response_message(out, 0, "successfully created ldap account"); + + /* errors that occur after this point are not fatal */ + + if ((group_stat = ceo_add_group(in->username, groups_base, id))) + response_message(out, ELDAP, "unable to create ldap group %s", in->username); + else + response_message(out, 0, "successfully created ldap group"); + + return krb_stat || user_stat || group_stat; +} + +static int32_t addclub(Ceo__AddUser *in, Ceo__AddUserResponse *out) { + char homedir[1024]; + int krb_stat, user_stat, group_stat, sudo_stat; + int id; + + if (snprintf(homedir, sizeof(homedir), "%s/%s", + club_home, in->username) >= sizeof(homedir)) + fatal("homedir overflow"); + + if ((id = ceo_new_uid(club_min_id, club_max_id)) <= 0) + fatal("no available uids in range [%ld, %ld]", club_min_id, club_max_id); + + if ((krb_stat = ceo_del_princ(in->username))) + return response_message(out, EKERB, "unable to clear principal %s", in->username); + + if ((user_stat = ceo_add_user(in->username, users_base, "club", in->realname, homedir, + club_shell, id, NULL))) + return response_message(out, ELDAP, "unable to create ldap account %s", in->username); + response_message(out, 0, "successfully created ldap account"); + + /* errors that occur after this point are not fatal */ + + if ((group_stat = ceo_add_group(in->username, groups_base, id))) + response_message(out, ELDAP, "unable to create ldap group %s", in->username); + else + response_message(out, 0, "successfully created ldap group"); + + if ((sudo_stat = ceo_add_group_sudo(in->username, sudo_base))) + response_message(out, ELDAP, "unable to create ldap sudoers %s", in->username); + else + response_message(out, 0, "successfully created ldap sudoers"); + + return user_stat || group_stat || sudo_stat; +} + +static int32_t adduser(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *client) { + int32_t chk_stat, status; + char *prog; + + chk_stat = check_adduser(in, out, client); + if (chk_stat) + return chk_stat; + + if (in->type == CEO__ADD_USER__TYPE__MEMBER) { + status = addmember(in, out); + prog = "addmember"; + } else if (in->type == CEO__ADD_USER__TYPE__CLUB) { + status = addclub(in, out); + prog = "addclub"; + } else { + fatal("unknown user type %d", in->type); + } + + if (status) + response_message(out, 0, "there were failures, please contact systems committee"); + + adduser_spam(in, out, client, prog, status); + + return status; +} + +void cmd_adduser(void) { + Ceo__AddUser *in_proto; + Ceo__AddUserResponse *out_proto = response_create(); + struct strbuf in = STRBUF_INIT; + struct strbuf out = STRBUF_INIT; + + if (strbuf_read(&in, STDIN_FILENO, 0) < 0) + fatalpe("read"); + + in_proto = ceo__add_user__unpack(&protobuf_c_default_allocator, + in.len, (uint8_t *)in.buf); + if (!in_proto) + fatal("malformed add user message"); + + char *client = getenv("CEO_USER"); + if (!client) + fatal("environment variable CEO_USER is not set"); + + adduser(in_proto, out_proto, client); + + strbuf_grow(&out, ceo__add_user_response__get_packed_size(out_proto)); + strbuf_setlen(&out, ceo__add_user_response__pack(out_proto, (uint8_t *)out.buf)); + full_write(STDOUT_FILENO, out.buf, out.len); + + ceo__add_user__free_unpacked(in_proto, &protobuf_c_default_allocator); + response_delete(out_proto); + + strbuf_release(&in); + strbuf_release(&out); +} + +int main(int argc, char *argv[]) { + prog = basename(argv[0]); + init_log(prog, LOG_PID, LOG_AUTHPRIV); + + configure(); + + if (setenv("KRB5CCNAME", "MEMORY:adduser", 1)) + fatalpe("setenv"); + + ceo_krb5_init(); + ceo_ldap_init(); + ceo_kadm_init(); + + cmd_adduser(); + + ceo_kadm_cleanup(); + ceo_ldap_cleanup(); + ceo_krb5_cleanup(); + + return 0; +} From a39d2b84850a9e813859d85539b3e02f6db5a85b Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 01:47:28 -0500 Subject: [PATCH 04/40] Call ceod in addmember and addclub --- src/addclub.c | 147 +++++++++++----------------------------------- src/addmember.c | 151 ++++++++++++------------------------------------ 2 files changed, 71 insertions(+), 227 deletions(-) diff --git a/src/addclub.c b/src/addclub.c index d905d48..487ba9f 100644 --- a/src/addclub.c +++ b/src/addclub.c @@ -18,153 +18,72 @@ #include "krb5.h" #include "kadm.h" #include "addhomedir.h" +#include "ceo.pb-c.h" char *prog = NULL; -char *user = NULL; -int privileged = 0; - -static int force = 0; -static int no_notify = 0; static char *name = NULL; static char *userid = NULL; static struct option opts[] = { - { "force", 0, NULL, 'f' }, - { "no-notify", 0, NULL, 'q' }, { NULL, 0, NULL, '\0' }, }; +const char *default_lib_dir = "/usr/lib/ceod"; +const char *lib_dir; + static void usage() { fprintf(stderr, "Usage: %s userid clubname\n", prog); exit(2); } -int addclub() { - int krb_ok, user_ok, group_ok, sudo_ok, home_ok; - int id; - char homedir[1024]; - char acl_s[1024] = {0}; +int addclub(void) { + struct strbuf preq = STRBUF_INIT; + struct strbuf pret = STRBUF_INIT; + char cpath[1024]; + char *cargv[] = { "ceoc", "adduser", NULL }; - notice("adding uid=%s cn=%s by %s", userid, name, user); + if (snprintf(cpath, sizeof(cpath), "%s/ceoc", lib_dir) >= sizeof(cpath)) + fatal("path too long"); - if (setreuid(0, 0)) - fatalpe("setreuid"); - if (setregid(0, 0)) - fatalpe("setregid"); + Ceo__AddUser req; + ceo__add_user__init(&req); - if (!force && getpwnam(userid) != NULL) - deny("user %s already exists", userid); + req.username = userid; + req.realname = name; + req.type = CEO__ADD_USER__TYPE__CLUB; - snprintf(homedir, sizeof(homedir), "%s/%s", club_home, userid); - ceo_krb5_init(); - ceo_ldap_init(); - ceo_kadm_init(); + strbuf_grow(&preq, ceo__add_user__get_packed_size(&req)); + strbuf_setlen(&preq, ceo__add_user__pack(&req, (uint8_t *)preq.buf)); - if (ceo_user_exists(userid)) - deny("user %s already exists in LDAP", userid); - if (ceo_group_exists(userid)) - deny("group %s already exists in LDAP", userid); + if (spawnvem(cpath, cargv, environ, &preq, &pret, 0)) + return 1; - if ((id = ceo_new_uid(club_min_id, club_max_id)) <= 0) - fatal("no available uids in range [%zd, %zd]", club_min_id, club_max_id); + Ceo__AddUserResponse *ret = ceo__add_user_response__unpack(&protobuf_c_default_allocator, + pret.len, (uint8_t *)pret.buf); + if (!ret) + fatal("failed to unpack response"); - snprintf(acl_s, sizeof(acl_s), club_home_acl, userid); - - krb_ok = ceo_del_princ(userid); - if (!krb_ok) - notice("successfully cleared principal for %s", userid); - - user_ok = krb_ok || ceo_add_user(userid, users_base, "club", name, homedir, - club_shell, id, NULL); - if (!user_ok) - notice("successfully created account for %s", userid); - - group_ok = user_ok || ceo_add_group(userid, groups_base, id); - if (!group_ok) - notice("successfully created group for %s", userid); - - sudo_ok = user_ok || ceo_add_group_sudo(userid, sudo_base); - if (!sudo_ok) - notice("successfully added group sudo entry for %s", userid); - - home_ok = user_ok || ceo_create_home(homedir, refquota, id, id, homedir_mode, acl_s); - if (!home_ok) - notice("successfully created home directory for %s", userid); - - notice("done uid=%s", userid); - - if (!no_notify && !user_ok) { - int pid; - int hkp[2]; - FILE *hkf; - int status; - - if (pipe(hkp)) - errorpe("pipe"); - - fflush(stdout); - fflush(stderr); - - pid = fork(); - - if (!pid) { - fclose(stdout); - fclose(stderr); - close(hkp[1]); - dup2(hkp[0], 0); - exit(execl(notify_hook, notify_hook, prog, user, userid, name, NULL)); - } - - hkf = fdopen(hkp[1], "w"); - - if (group_ok) - fprintf(hkf, "failed to create group\n"); - if (home_ok) - fprintf(hkf, "failed to create home directory\n"); - if (!group_ok && !home_ok) - fprintf(hkf, "all failures went undetected\n"); - - fclose(hkf); - - waitpid(pid, &status, 0); - - if (WIFEXITED(status) && WEXITSTATUS(status)) - notice("hook %s exited with status %d", notify_hook, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - notice("hook %s killed by signal %d", notify_hook, WTERMSIG(status)); + for (int i = 0; i < ret->n_messages; i++) { + if (ret->messages[i]->status) + error("%s", ret->messages[i]->message); + else + notice("%s", ret->messages[i]->message); } - ceo_kadm_cleanup(); - ceo_ldap_cleanup(); - ceo_krb5_cleanup(); - - return krb_ok || user_ok || group_ok || home_ok; + return 0; } int main(int argc, char *argv[]) { int opt; prog = basename(argv[0]); - init_log(prog, LOG_PID, LOG_AUTHPRIV); + init_log(prog, 0, LOG_AUTHPRIV); configure(); - user = ceo_get_user(); - privileged = ceo_get_privileged(); - while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) { switch (opt) { - case 'f': - if (!privileged) - deny("not privileged enough to force"); - force = 1; - break; - case 'q': - if (!privileged) - deny("not privileged enough to suppress notifications"); - no_notify = 1; - break; case '?': usage(); break; @@ -173,11 +92,13 @@ int main(int argc, char *argv[]) { } } - if (argc - optind != 2) + if (argc - optind != 2 && argc - optind != 3) usage(); userid = argv[optind++]; name = argv[optind++]; + lib_dir = getenv("CEO_LIB_DIR") ?: default_lib_dir; + return addclub(); } diff --git a/src/addmember.c b/src/addmember.c index bd227f1..9d29017 100644 --- a/src/addmember.c +++ b/src/addmember.c @@ -18,13 +18,9 @@ #include "krb5.h" #include "kadm.h" #include "addhomedir.h" +#include "ceo.pb-c.h" char *prog = NULL; -char *user = NULL; -int privileged = 0; - -static int force = 0; -static int no_notify = 0; static int use_stdin = 0; @@ -34,148 +30,73 @@ static char *program = NULL; static char password[1024]; static struct option opts[] = { - { "force", 0, NULL, 'f' }, - { "no-notify", 0, NULL, 'q' }, { "stdin", 0, NULL, 's' }, { NULL, 0, NULL, '\0' }, }; +const char *default_lib_dir = "/usr/lib/ceod"; +const char *lib_dir; + static void usage() { fprintf(stderr, "Usage: %s userid realname [program]\n", prog); exit(2); } -int addmember() { - int krb_ok, user_ok, group_ok, home_ok; - int id; - char homedir[1024]; - char acl_s[1024] = {0}; +int addmember(void) { + struct strbuf preq = STRBUF_INIT; + struct strbuf pret = STRBUF_INIT; + char cpath[1024]; + char *cargv[] = { "ceoc", "adduser", NULL }; - notice("adding uid=%s cn=%s program=%s by %s", userid, name, program, user); - - if (setreuid(0, 0)) - fatalpe("setreuid"); - if (setregid(0, 0)) - fatalpe("setregid"); - - if (!force && getpwnam(userid) != NULL) - deny("user %s already exists", userid); - - snprintf(homedir, sizeof(homedir), "%s/%s", member_home, userid); + if (snprintf(cpath, sizeof(cpath), "%s/ceoc", lib_dir) >= sizeof(cpath)) + fatal("path too long"); if (ceo_read_password(password, sizeof(password), use_stdin)) return 1; - ceo_krb5_init(); - ceo_ldap_init(); - ceo_kadm_init(); + Ceo__AddUser req; + ceo__add_user__init(&req); - if (ceo_user_exists(userid)) - deny("user %s already exists in LDAP", userid); - if (ceo_group_exists(userid)) - deny("group %s already exists in LDAP", userid); + req.username = userid; + req.password = password; + req.program = program; + req.realname = name; + req.type = CEO__ADD_USER__TYPE__MEMBER; - if ((id = ceo_new_uid(member_min_id, member_max_id)) <= 0) - fatal("no available uids in range [%zd, %zd]", member_min_id, member_max_id); + strbuf_grow(&preq, ceo__add_user__get_packed_size(&req)); + strbuf_setlen(&preq, ceo__add_user__pack(&req, (uint8_t *)preq.buf)); - if (*member_home_acl) { - snprintf(acl_s, sizeof(acl_s), member_home_acl, userid); + if (spawnvem(cpath, cargv, environ, &preq, &pret, 0)) + return 1; + + Ceo__AddUserResponse *ret = ceo__add_user_response__unpack(&protobuf_c_default_allocator, + pret.len, (uint8_t *)pret.buf); + if (!ret) + fatal("failed to unpack response"); + + for (int i = 0; i < ret->n_messages; i++) { + if (ret->messages[i]->status) + error("%s", ret->messages[i]->message); + else + notice("%s", ret->messages[i]->message); } - krb_ok = ceo_del_princ(userid); - krb_ok = krb_ok || ceo_add_princ(userid, password); - if (!krb_ok) - notice("successfully created principal for %s", userid); - - user_ok = krb_ok || ceo_add_user(userid, users_base, "member", name, homedir, - member_shell, id, "program", program, NULL); - if (!user_ok) - notice("successfully created account for %s", userid); - - group_ok = user_ok || ceo_add_group(userid, groups_base, id); - if (!group_ok) - notice("successfully created group for %s", userid); - - home_ok = user_ok || ceo_create_home(homedir, refquota, id, id, homedir_mode, acl_s); - if (!home_ok) - notice("successfully created home directory for %s", userid); - - notice("done uid=%s", userid); - - if (!no_notify && !user_ok) { - int pid; - int hkp[2]; - FILE *hkf; - int status; - - if (pipe(hkp)) - errorpe("pipe"); - - fflush(stdout); - fflush(stderr); - - pid = fork(); - - if (!pid) { - fclose(stdout); - fclose(stderr); - close(hkp[1]); - dup2(hkp[0], 0); - exit(execl(notify_hook, notify_hook, prog, user, userid, name, program, NULL)); - } - - hkf = fdopen(hkp[1], "w"); - - if (group_ok) - fprintf(hkf, "failed to create group\n"); - if (home_ok) - fprintf(hkf, "failed to create home directory\n"); - if (!group_ok && !home_ok) - fprintf(hkf, "all failures went undetected\n"); - - fclose(hkf); - - waitpid(pid, &status, 0); - - if (WIFEXITED(status) && WEXITSTATUS(status)) - notice("hook %s exited with status %d", notify_hook, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - notice("hook %s killed by signal %d", notify_hook, WTERMSIG(status)); - } - - ceo_kadm_cleanup(); - ceo_ldap_cleanup(); - ceo_krb5_cleanup(); - - return krb_ok || user_ok || group_ok || home_ok; + return 0; } int main(int argc, char *argv[]) { int opt; prog = basename(argv[0]); - init_log(prog, LOG_PID, LOG_AUTHPRIV); + init_log(prog, 0, LOG_AUTHPRIV); configure(); - user = ceo_get_user(); - privileged = ceo_get_privileged(); - while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) { switch (opt) { case 's': use_stdin = 1; break; - case 'f': - if (!privileged) - deny("not privileged enough to force"); - force = 1; - break; - case 'q': - if (!privileged) - deny("not privileged enough to suppress notifications"); - no_notify = 1; - break; case '?': usage(); break; @@ -193,5 +114,7 @@ int main(int argc, char *argv[]) { if (argc - optind) program = argv[optind++]; + lib_dir = getenv("CEO_LIB_DIR") ?: default_lib_dir; + return addmember(); } From 7a7c1fcc41dee47728224d4271100e8cbe103be7 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 01:48:04 -0500 Subject: [PATCH 05/40] Update .gitignore --- src/.gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/.gitignore b/src/.gitignore index 05746e8..a7b37bf 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -3,5 +3,11 @@ .nfs* /addmember /addclub +/adduser +/op-adduser /zfsaddhomedir /config-test +/ceod +/ceoc +/ceo.pb-c.c +/ceo.pb-c.h From 64f10c6009eedeb41ef0b950b876e5cf8da463aa Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 01:52:49 -0500 Subject: [PATCH 06/40] Adjust Makefile --- src/Makefile | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Makefile b/src/Makefile index f1d94bb..74e58a0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,9 +11,6 @@ BIN_PROGS := addmember addclub zfsaddhomedir ceod LIB_PROGS := ceoc op-adduser EXT_PROGS := config-test -LIBCEO_OBJECTS := common.o addhomedir.o -LIBCEO_LDFLAGS := -LIBCEO_PROGS := addmember addclub LDAP_OBJECTS := ldap.o LDAP_LDFLAGS := -lldap LDAP_PROGS := addmember addclub op-adduser @@ -25,10 +22,10 @@ NET_LDFLAGS := -lsctp $(shell krb5-config --libs gssapi) NET_PROGS := ceod ceoc PROTO_OBJECTS := ceo.pb-c.o PROTO_LDFLAGS := -lprotobuf-c -PROTO_PROGS := op-adduser +PROTO_PROGS := op-adduser addmember addclub CONFIG_OBJECTS := config.o parser.o CONFIG_LDFLAGS := -CONFIG_PROGS := $(OLDCEO_PROGS) $(LDAP_PROGS) $(KRB5_PROGS) $(NET_PROGS) +CONFIG_PROGS := $(LDAP_PROGS) $(KRB5_PROGS) $(NET_PROGS) UTIL_OBJECTS := util.o strbuf.o UTIL_PROGS := config-test zfsaddhomedir $(CONFIG_PROGS) @@ -50,13 +47,13 @@ config-test: config-test.o parser.o config.o: config.h config-vars.h install: - install -d $(DESTDIR)$(PREFIX)/bin - install addmember addclub $(DESTDIR)$(PREFIX)/bin + install -d $(DESTDIR)$(PREFIX)/sbin $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/lib/ceod + install ceod $(DESTDIR)$(PREFIX)/sbin + install op-adduser addmember addclub $(DESTDIR)$(PREFIX)/bin + install ceoc op-adduser $(DESTDIR)$(PREFIX)/lib/ceod $(NET_PROGS): LDFLAGS += $(NET_LDFLAGS) $(NET_PROGS): $(NET_OBJECTS) -$(LIBCEO_PROGS): LDFLAGS += $(LIBCEO_LDFLAGS) -$(LIBCEO_PROGS): $(LIBCEO_OBJECTS) $(LDAP_PROGS): LDFLAGS += $(LDAP_LDFLAGS) $(LDAP_PROGS): $(LDAP_OBJECTS) $(KRB5_PROGS): LDFLAGS += $(KRB5_LDFLAGS) @@ -69,4 +66,4 @@ $(UTIL_PROGS): LDFLAGS += $(UTIL_LDFLAGS) $(UTIL_PROGS): $(UTIL_OBJECTS) .PHONY: clean all -.SECONDARY: zfsaddhomedir.o addmember.o addclub.o +.SECONDARY: ceoc.o zfsaddhomedir.o addmember.o addclub.o From 6752ed1bc4014b2dcb5a44118e4a6ca42d44fa27 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 01:53:10 -0500 Subject: [PATCH 07/40] Remove obsolete code --- src/addclub.c | 2 -- src/addhomedir.c | 35 ----------------------------- src/addhomedir.h | 3 --- src/addmember.c | 2 -- src/common.c | 58 ------------------------------------------------ src/common.h | 3 --- 6 files changed, 103 deletions(-) delete mode 100644 src/addhomedir.c delete mode 100644 src/addhomedir.h delete mode 100644 src/common.c delete mode 100644 src/common.h diff --git a/src/addclub.c b/src/addclub.c index 487ba9f..1442b03 100644 --- a/src/addclub.c +++ b/src/addclub.c @@ -12,12 +12,10 @@ #include #include "util.h" -#include "common.h" #include "config.h" #include "ldap.h" #include "krb5.h" #include "kadm.h" -#include "addhomedir.h" #include "ceo.pb-c.h" char *prog = NULL; diff --git a/src/addhomedir.c b/src/addhomedir.c deleted file mode 100644 index c342ffe..0000000 --- a/src/addhomedir.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "addhomedir.h" -#include "util.h" -#include "config.h" -#include "krb5.h" - -int ceo_create_home(char *homedir, char *refquota, uid_t uid, gid_t gid, char *mode, char *acl) { - char uid_str[16], gid_str[16]; - char *zfs_argv[] = { "ssh", "ceo@ginseng", "/usr/sbin/zfsaddhomedir", \ - homedir, refquota, skeleton_dir, uid_str, gid_str, mode, acl, NULL }; - int ret = 0; - - assert(homedir[0]); - snprintf(uid_str, sizeof(uid_str), "%ld", (long)uid); - snprintf(gid_str, sizeof(gid_str), "%ld", (long)uid); - if(!acl[0]) acl = NULL; - - ceo_krb5_auth(admin_bind_userid, admin_bind_keytab); - if(spawnv("/usr/bin/ssh", zfs_argv)) { - errorpe("failed calling zfsaddhomedir for %s", homedir); - ret = -1; - } - ceo_krb5_deauth(); - - return ret; -} diff --git a/src/addhomedir.h b/src/addhomedir.h deleted file mode 100644 index 6e0d091..0000000 --- a/src/addhomedir.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int ceo_create_home(char *, char *, uid_t, gid_t, char *, char *); diff --git a/src/addmember.c b/src/addmember.c index 9d29017..183ccdd 100644 --- a/src/addmember.c +++ b/src/addmember.c @@ -12,12 +12,10 @@ #include #include "util.h" -#include "common.h" #include "config.h" #include "ldap.h" #include "krb5.h" #include "kadm.h" -#include "addhomedir.h" #include "ceo.pb-c.h" char *prog = NULL; diff --git a/src/common.c b/src/common.c deleted file mode 100644 index 24edc90..0000000 --- a/src/common.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include -#include - -#include "common.h" -#include "util.h" -#include "config.h" - -int ceo_get_privileged() { - int uid = getuid(); - - // root is privileged - if (!uid) - return 1; - - if (privileged_group) { - struct group *privgrp = getgrnam(privileged_group); - int pgid; - gid_t grps[128]; - int count, i; - if (!privgrp) - return 0; - pgid = privgrp->gr_gid; - - count = getgroups(sizeof(grps), grps); - for (i = 0; i < count; i++) - if (grps[i] == pgid) - return 1; - } - - return 0; -} - -char *ceo_get_user() { - struct passwd *pwent = getpwuid(getuid()); - if (pwent == NULL) - fatal("could not determine user"); - return xstrdup(pwent->pw_name); -} - -void ceo_notify_hook(int argc, ...) { - va_list args; - char **argv; - int i = 0; - - va_start(args, argc); - - argv = (char **)xmalloc(sizeof(char *) * (argc + 1)); - - while (i < argc) - argv[i++] = va_arg(args, char *); - - argv[i++] = NULL; - spawnv(notify_hook, argv); - - va_end(args); -} diff --git a/src/common.h b/src/common.h deleted file mode 100644 index cd17722..0000000 --- a/src/common.h +++ /dev/null @@ -1,3 +0,0 @@ -int ceo_get_privileged(); -char *ceo_get_user(); -void ceo_notify_hook(int, ...); From 99aa8e0fca18866f8e9aa27059f7231d26656858 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 02:03:47 -0500 Subject: [PATCH 08/40] Fix clean --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 74e58a0..56a9a2e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,7 +32,7 @@ UTIL_PROGS := config-test zfsaddhomedir $(CONFIG_PROGS) all: $(BIN_PROGS) $(LIB_PROGS) $(EXT_PROGS) clean: - rm -f $(ALL_PROGS) $(EXT_PROGS) *.o ceo.pb-c.c ceo.pb-c.h + rm -f $(BIN_PROGS) $(LIB_PROGS) $(EXT_PROGS) *.o ceo.pb-c.c ceo.pb-c.h op-adduser.o addmember.o addclub.o: ceo.pb-c.h From 87a353db17d8401631f27778334a181e88fdc918 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 02:05:41 -0500 Subject: [PATCH 09/40] Don't install op-adduser to /usr/bin --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 56a9a2e..5dff35f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -49,7 +49,7 @@ config.o: config.h config-vars.h install: install -d $(DESTDIR)$(PREFIX)/sbin $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/lib/ceod install ceod $(DESTDIR)$(PREFIX)/sbin - install op-adduser addmember addclub $(DESTDIR)$(PREFIX)/bin + install addmember addclub $(DESTDIR)$(PREFIX)/bin install ceoc op-adduser $(DESTDIR)$(PREFIX)/lib/ceod $(NET_PROGS): LDFLAGS += $(NET_LDFLAGS) From 2806b4a15ef600c2895040a07b78fff15aad1940 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 16:32:23 -0500 Subject: [PATCH 10/40] Nothing to see here --- src/util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/util.c b/src/util.c index 3078d23..6b0a5b4 100644 --- a/src/util.c +++ b/src/util.c @@ -29,6 +29,8 @@ static void errmsg(int prio, const char *prefix, const char *fmt, va_list args) syslog(prio, "%s", msg.buf); if (log_stderr) fputs(msg.buf, stderr); + + strbuf_release(&msg); } static void errmsgpe(int prio, const char *prefix, const char *fmt, va_list args) { @@ -41,6 +43,8 @@ static void errmsgpe(int prio, const char *prefix, const char *fmt, va_list args syslog(prio, "%s", msg.buf); if (log_stderr) fputs(msg.buf, stderr); + + strbuf_release(&msg); } NORETURN static void die(int prio, const char *prefix, const char *msg, va_list args) { From 49004af3ca88f0107cdbd7f7e882931d6a1d04d2 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 17:34:59 -0500 Subject: [PATCH 11/40] Free everything before exiting This cleans up valgrind --show-reachable. --- src/addclub.c | 14 ++++++++-- src/addmember.c | 14 ++++++++-- src/ceoc.c | 14 ++++++++-- src/config.c | 11 +++++++- src/config.h | 3 ++- src/dmaster.c | 14 ++++++++-- src/dslave.c | 7 +++++ src/gss.c | 69 +++++++++++++++++++++++++++++++++++++----------- src/gss.h | 1 + src/net.c | 4 +++ src/net.h | 1 + src/op-adduser.c | 5 +++- src/ops.c | 11 ++++++++ src/ops.h | 1 + 14 files changed, 142 insertions(+), 27 deletions(-) diff --git a/src/addclub.c b/src/addclub.c index 1442b03..27b4f94 100644 --- a/src/addclub.c +++ b/src/addclub.c @@ -69,13 +69,18 @@ int addclub(void) { notice("%s", ret->messages[i]->message); } + ceo__add_user_response__free_unpacked(ret, &protobuf_c_default_allocator); + strbuf_release(&preq); + strbuf_release(&pret); + return 0; } int main(int argc, char *argv[]) { int opt; + int ret; - prog = basename(argv[0]); + prog = xstrdup(basename(argv[0])); init_log(prog, 0, LOG_AUTHPRIV); configure(); @@ -98,5 +103,10 @@ int main(int argc, char *argv[]) { lib_dir = getenv("CEO_LIB_DIR") ?: default_lib_dir; - return addclub(); + ret = addclub(); + + free_config(); + free(prog); + + return ret; } diff --git a/src/addmember.c b/src/addmember.c index 183ccdd..138a356 100644 --- a/src/addmember.c +++ b/src/addmember.c @@ -79,13 +79,18 @@ int addmember(void) { notice("%s", ret->messages[i]->message); } + ceo__add_user_response__free_unpacked(ret, &protobuf_c_default_allocator); + strbuf_release(&preq); + strbuf_release(&pret); + return 0; } int main(int argc, char *argv[]) { int opt; + int ret; - prog = basename(argv[0]); + prog = xstrdup(basename(argv[0])); init_log(prog, 0, LOG_AUTHPRIV); configure(); @@ -114,5 +119,10 @@ int main(int argc, char *argv[]) { lib_dir = getenv("CEO_LIB_DIR") ?: default_lib_dir; - return addmember(); + ret = addmember(); + + free_config(); + free(prog); + + return ret; } diff --git a/src/ceoc.c b/src/ceoc.c index a4899f7..1eb6d78 100644 --- a/src/ceoc.c +++ b/src/ceoc.c @@ -136,13 +136,15 @@ int client_main(char *op_name) { int main(int argc, char *argv[]) { int opt; + int ret; char *op; - prog = basename(argv[0]); + prog = xstrdup(basename(argv[0])); init_log(prog, 0, LOG_USER); configure(); setup_ops(); + setup_fqdn(); while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) { switch (opt) { @@ -159,5 +161,13 @@ int main(int argc, char *argv[]) { op = argv[optind++]; - return client_main(op); + ret = client_main(op); + + free_gss(); + free_fqdn(); + free_config(); + free_ops(); + free(prog); + + return ret; } diff --git a/src/config.c b/src/config.c index d08b260..7dffe9e 100644 --- a/src/config.c +++ b/src/config.c @@ -54,7 +54,7 @@ void config_var(char *var, char *val) { } } -void configure() { +void configure(void) { int i; char conffile[1024]; @@ -80,3 +80,12 @@ void configure() { } } } + +void free_config(void) { + for (int i = 0; i < sizeof(config_vars)/sizeof(*config_vars); i++) { + if (config_vars[i].type == CONFIG_TYPE_STR) { + free(*(char **)config_vars[i].p); + *(char **)config_vars[i].p = NULL; + } + } +} diff --git a/src/config.h b/src/config.h index 789843f..57527c5 100644 --- a/src/config.h +++ b/src/config.h @@ -4,6 +4,7 @@ #undef CONFIG_STR #undef CONFIG_INT -void configure(); +void configure(void); +void free_config(void); extern const char *config_dir; diff --git a/src/dmaster.c b/src/dmaster.c index d2d40f3..e621ade 100644 --- a/src/dmaster.c +++ b/src/dmaster.c @@ -142,13 +142,18 @@ static int master_main(void) { while (!terminate) accept_one_client(sock); + free_gss(); + free_fqdn(); + free_ops(); + return 0; } int main(int argc, char *argv[]) { int opt; + int ret; - prog = basename(argv[0]); + prog = xstrdup(basename(argv[0])); init_log(prog, LOG_PID, LOG_DAEMON); configure(); @@ -169,5 +174,10 @@ int main(int argc, char *argv[]) { if (argc != optind) usage(); - return master_main(); + ret = master_main(); + + free_config(); + free(prog); + + return ret; } diff --git a/src/dslave.c b/src/dslave.c index 0001372..f62e0a5 100644 --- a/src/dslave.c +++ b/src/dslave.c @@ -142,5 +142,12 @@ void slave_main(int sock, struct sockaddr *addr) { notice("connection closed by peer %s", addrstr); strbuf_release(&msg); + + /* stuff allocated by dmaster */ + free_gss(); + free_config(); + free_fqdn(); + free_ops(); + free(prog); } diff --git a/src/gss.c b/src/gss.c index 9305ce6..13d0c6d 100644 --- a/src/gss.c +++ b/src/gss.c @@ -12,13 +12,43 @@ static gss_cred_id_t my_creds = GSS_C_NO_CREDENTIAL; static gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT; static gss_name_t peer_name = GSS_C_NO_NAME; static gss_name_t imported_service = GSS_C_NO_NAME; -static gss_OID mech_type = GSS_C_NO_OID; -static gss_buffer_desc peer_principal; +static char *peer_principal; static char *peer_username; static OM_uint32 ret_flags; static int complete; char service_name[128]; +void free_gss(void) { + OM_uint32 maj_stat, min_stat; + + if (peer_name) { + maj_stat = gss_release_name(&min_stat, &peer_name); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_release_name", maj_stat, min_stat); + } + + if (imported_service) { + maj_stat = gss_release_name(&min_stat, &imported_service); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_release_name", maj_stat, min_stat); + } + + if (context_handle) { + maj_stat = gss_delete_sec_context(&min_stat, &context_handle, GSS_C_NO_BUFFER); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_delete_sec_context", maj_stat, min_stat); + } + + if (my_creds) { + maj_stat = gss_release_cred(&min_stat, &my_creds); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_release_creds", maj_stat, min_stat); + } + + free(peer_principal); + free(peer_username); +} + static void display_status(char *prefix, OM_uint32 code, int type) { OM_uint32 maj_stat, min_stat; gss_buffer_desc msg; @@ -101,28 +131,44 @@ void client_acquire_creds(const char *service, const char *hostname) { import_service(service, hostname); } +static char *princ_to_username(char *princ) { + char *ret = xstrdup(princ); + char *c = strchr(ret, '@'); + if (c) + *c = '\0'; + return ret; +} + int process_server_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok) { OM_uint32 maj_stat, min_stat; OM_uint32 time_rec; gss_OID name_type; + gss_buffer_desc peer_princ; if (complete) fatal("unexpected %zd-byte token from peer", incoming_tok->length); maj_stat = gss_accept_sec_context(&min_stat, &context_handle, my_creds, - incoming_tok, GSS_C_NO_CHANNEL_BINDINGS, &peer_name, &mech_type, + incoming_tok, GSS_C_NO_CHANNEL_BINDINGS, &peer_name, NULL, outgoing_tok, &ret_flags, &time_rec, NULL); if (maj_stat == GSS_S_COMPLETE) { check_services(ret_flags); complete = 1; - maj_stat = gss_display_name(&min_stat, peer_name, &peer_principal, &name_type); + maj_stat = gss_display_name(&min_stat, peer_name, &peer_princ, &name_type); if (maj_stat != GSS_S_COMPLETE) gss_fatal("gss_display_name", maj_stat, min_stat); - notice("client authenticated as %s", (char *)peer_principal.value); - debug("context expires in %d seconds",time_rec); + peer_principal = xstrdup((char *)peer_princ.value); + peer_username = princ_to_username((char *)peer_princ.value); + + notice("client authenticated as %s", peer_principal); + debug("context expires in %d seconds", time_rec); + + maj_stat = gss_release_buffer(&min_stat, &peer_princ); + if (maj_stat != GSS_S_COMPLETE) + gss_fatal("gss_release_buffer", maj_stat, min_stat); } else if (maj_stat != GSS_S_CONTINUE_NEEDED) { gss_fatal("gss_accept_sec_context", maj_stat, min_stat); @@ -165,19 +211,10 @@ int initial_client_token(gss_buffer_t outgoing_tok) { } char *client_principal(void) { - return complete ? (char *)peer_principal.value : NULL; + return peer_principal; } char *client_username(void) { - if (!peer_username) { - char *princ = client_principal(); - if (princ) { - peer_username = xstrdup(princ); - char *c = strchr(peer_username, '@'); - if (c) - *c = '\0'; - } - } return peer_username; } diff --git a/src/gss.h b/src/gss.h index 7e7c290..9a14a61 100644 --- a/src/gss.h +++ b/src/gss.h @@ -9,3 +9,4 @@ int process_client_token(gss_buffer_t incoming_tok, gss_buffer_t outgoing_tok); int initial_client_token(gss_buffer_t outgoing_tok); char *client_principal(void); char *client_username(void); +void free_gss(void); diff --git a/src/net.c b/src/net.c index 825c917..f46e5c1 100644 --- a/src/net.c +++ b/src/net.c @@ -26,6 +26,10 @@ void setup_fqdn(void) { strbuf_addstr(&fqdn, lo->h_name); } +void free_fqdn(void) { + strbuf_release(&fqdn); +} + static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg, int *notification) { size_t len = 0; int flags; diff --git a/src/net.h b/src/net.h index 0e6ac9f..45a4a06 100644 --- a/src/net.h +++ b/src/net.h @@ -22,6 +22,7 @@ typedef struct sockaddr sa; extern struct strbuf fqdn; extern void setup_fqdn(void); +extern void free_fqdn(void); struct sctp_meta { struct sockaddr_storage from; diff --git a/src/op-adduser.c b/src/op-adduser.c index 5e1990e..0d54508 100644 --- a/src/op-adduser.c +++ b/src/op-adduser.c @@ -261,7 +261,7 @@ void cmd_adduser(void) { } int main(int argc, char *argv[]) { - prog = basename(argv[0]); + prog = xstrdup(basename(argv[0])); init_log(prog, LOG_PID, LOG_AUTHPRIV); configure(); @@ -279,5 +279,8 @@ int main(int argc, char *argv[]) { ceo_ldap_cleanup(); ceo_krb5_cleanup(); + free_config(); + free(prog); + return 0; } diff --git a/src/ops.c b/src/ops.c index 9cf53c3..857f633 100644 --- a/src/ops.c +++ b/src/ops.c @@ -102,9 +102,20 @@ void setup_ops(void) { strbuf_list_free(words); } + fclose(fp); } closedir(dp); strbuf_release(&line); } +void free_ops(void) { + while (ops) { + struct op *next = ops->next; + free(ops->name); + free(ops->hostname); + free(ops->path); + free(ops); + ops = next; + } +} diff --git a/src/ops.h b/src/ops.h index 21ee45a..3e7465c 100644 --- a/src/ops.h +++ b/src/ops.h @@ -9,5 +9,6 @@ struct op { }; void setup_ops(void); +void free_ops(void); struct op *find_op(const char *name); struct op *get_local_op(uint32_t id); From a26181a2785af311e89b95fd3c2cc391b399755c Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 18:10:39 -0500 Subject: [PATCH 12/40] Revert "Use rsync in zfsaddhomedir" This reverts commit 88952ae56a2572559a073667d9ef704087a7c479. --- src/zfsaddhomedir.c | 96 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 7 deletions(-) diff --git a/src/zfsaddhomedir.c b/src/zfsaddhomedir.c index 67de691..2774934 100644 --- a/src/zfsaddhomedir.c +++ b/src/zfsaddhomedir.c @@ -10,6 +10,7 @@ int main(int argc, char *argv[]) { return 1; } + // TODO: check return of spawnv { char *homedir = argv[1]; char *skeldir = argv[3]; @@ -19,13 +20,13 @@ int main(int argc, char *argv[]) { uid_t uid, gid; char *zfs_bin = "/usr/sbin/zfs"; char *chmod_bin = "/usr/bin/chmod"; - char *rsync_bin = "/usr/bin/rsync"; char *dataset = homedir + 1; char *create_argv[] = { "zfs", "create", dataset, NULL }; char *quota_argv[] = { "zfs", "set", refquota, dataset, NULL }; char *mode_argv[] = { "chmod", mode, homedir, NULL }; char *acl_argv[] = { "chmod", acl, homedir, NULL }; - char *rsync_argv[] = { "rsync", "-avH", skeldir, homedir, NULL }; + DIR *skel; + struct dirent *skelent; assert(homedir[0]); uid = atol(argv[4]); @@ -41,15 +42,96 @@ int main(int argc, char *argv[]) { if(acl && spawnv(chmod_bin, acl_argv)) return 1; + skel = opendir(skeldir); + if (!skel) { + errorpe("failed to open %s", skeldir); + return -1; + } + + while ((skelent = readdir(skel))) { + struct stat sb; + char src[PATH_MAX], dest[PATH_MAX]; + + if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, "..")) + continue; + + snprintf(src, sizeof(src), "%s/%s", skeldir, skelent->d_name); + snprintf(dest, sizeof(dest), "/%s/%s", homedir, skelent->d_name); + lstat(src, &sb); + + if (sb.st_uid || sb.st_gid) { + warn("not creating %s due to ownership", dest); + continue; + } + + if (S_ISREG(sb.st_mode)) { + int bytes; + char buf[4096]; + + int srcfd = open(src, O_RDONLY); + if (srcfd == -1) { + warnpe("open: %s", src); + continue; + } + + int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, sb.st_mode & 0777); + if (destfd == -1) { + warnpe("open: %s", dest); + close(srcfd); + continue; + } + + for (;;) { + bytes = read(srcfd, buf, sizeof(buf)); + if (!bytes) + break; + if (bytes < 0) { + warnpe("read"); + break; + } + if (write(destfd, buf, bytes) < 0) { + warnpe("write"); + break; + } + } + if (fchown(destfd, uid, gid)) + errorpe("chown: %s", dest); + + close(srcfd); + close(destfd); + } else if (S_ISDIR(sb.st_mode)) { + if (mkdir(dest, sb.st_mode & 0777)) { + warnpe("mkdir: %s", dest); + continue; + } + if (chown(dest, uid, gid)) + errorpe("chown: %s", dest); + } else if (S_ISLNK(sb.st_mode)) { + char lnkdest[PATH_MAX]; + int bytes; + bytes = readlink(src, lnkdest, sizeof(lnkdest)); + lnkdest[bytes] = '\0'; + if (bytes == -1) { + warnpe("readlink: %s", src); + continue; + } + if (symlink(lnkdest, dest)) { + warnpe("symlink: %s", dest); + continue; + } + if (lchown(dest, uid, gid)) + errorpe("lchown: %s", dest); + } else { + warn("not creating %s", dest); + } + } + + closedir(skel); + if (chown(homedir, uid, gid)) { errorpe("failed to chown %s", homedir); return -1; } - - if(seteuid(uid) != 0 || setegid(gid) != 0) - return 1; - if(spawnv(rsync_bin, rsync_argv)) - return 1; } return 0; From 8254cea7bfde3e2a44b8eed0cc26aa3d01711b39 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 18:43:19 -0500 Subject: [PATCH 13/40] Revert "I bet this speeds up the compilation" This reverts commit 6055aecb27e433b0de738f870085a9bf11323ab9. --- src/zfsaddhomedir.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/zfsaddhomedir.c b/src/zfsaddhomedir.c index 2774934..f3431b3 100644 --- a/src/zfsaddhomedir.c +++ b/src/zfsaddhomedir.c @@ -1,6 +1,10 @@ #include -#include #include +#include +#include +#include +#include +#include #include #include "util.h" From 27be3e67d9b3c0bb23ea80a908771336249b019e Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 31 Jan 2009 18:44:01 -0500 Subject: [PATCH 14/40] Remove pointless indentation --- src/zfsaddhomedir.c | 213 ++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 108 deletions(-) diff --git a/src/zfsaddhomedir.c b/src/zfsaddhomedir.c index f3431b3..ae556f6 100644 --- a/src/zfsaddhomedir.c +++ b/src/zfsaddhomedir.c @@ -14,129 +14,126 @@ int main(int argc, char *argv[]) { return 1; } - // TODO: check return of spawnv - { - char *homedir = argv[1]; - char *skeldir = argv[3]; - char refquota[32]; - char *mode = argv[6]; - char *acl = (argc >= 8) ? argv[7] : NULL; - uid_t uid, gid; - char *zfs_bin = "/usr/sbin/zfs"; - char *chmod_bin = "/usr/bin/chmod"; - char *dataset = homedir + 1; - char *create_argv[] = { "zfs", "create", dataset, NULL }; - char *quota_argv[] = { "zfs", "set", refquota, dataset, NULL }; - char *mode_argv[] = { "chmod", mode, homedir, NULL }; - char *acl_argv[] = { "chmod", acl, homedir, NULL }; - DIR *skel; - struct dirent *skelent; + char *homedir = argv[1]; + char *skeldir = argv[3]; + char refquota[32]; + char *mode = argv[6]; + char *acl = (argc >= 8) ? argv[7] : NULL; + uid_t uid, gid; + char *zfs_bin = "/usr/sbin/zfs"; + char *chmod_bin = "/usr/bin/chmod"; + char *dataset = homedir + 1; + char *create_argv[] = { "zfs", "create", dataset, NULL }; + char *quota_argv[] = { "zfs", "set", refquota, dataset, NULL }; + char *mode_argv[] = { "chmod", mode, homedir, NULL }; + char *acl_argv[] = { "chmod", acl, homedir, NULL }; + DIR *skel; + struct dirent *skelent; - assert(homedir[0]); - uid = atol(argv[4]); - gid = atol(argv[5]); - snprintf(refquota, sizeof(refquota), "refquota=%s", argv[2]); + assert(homedir[0]); + uid = atol(argv[4]); + gid = atol(argv[5]); + snprintf(refquota, sizeof(refquota), "refquota=%s", argv[2]); - if(spawnv(zfs_bin, create_argv)) - return 1; - if(spawnv(zfs_bin, quota_argv)) - return 1; - if(spawnv(chmod_bin, mode_argv)) - return 1; - if(acl && spawnv(chmod_bin, acl_argv)) - return 1; + if(spawnv(zfs_bin, create_argv)) + return 1; + if(spawnv(zfs_bin, quota_argv)) + return 1; + if(spawnv(chmod_bin, mode_argv)) + return 1; + if(acl && spawnv(chmod_bin, acl_argv)) + return 1; - skel = opendir(skeldir); - if (!skel) { - errorpe("failed to open %s", skeldir); - return -1; + skel = opendir(skeldir); + if (!skel) { + errorpe("failed to open %s", skeldir); + return -1; + } + + while ((skelent = readdir(skel))) { + struct stat sb; + char src[PATH_MAX], dest[PATH_MAX]; + + if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, "..")) + continue; + + snprintf(src, sizeof(src), "%s/%s", skeldir, skelent->d_name); + snprintf(dest, sizeof(dest), "/%s/%s", homedir, skelent->d_name); + lstat(src, &sb); + + if (sb.st_uid || sb.st_gid) { + warn("not creating %s due to ownership", dest); + continue; } - while ((skelent = readdir(skel))) { - struct stat sb; - char src[PATH_MAX], dest[PATH_MAX]; + if (S_ISREG(sb.st_mode)) { + int bytes; + char buf[4096]; - if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, "..")) - continue; - - snprintf(src, sizeof(src), "%s/%s", skeldir, skelent->d_name); - snprintf(dest, sizeof(dest), "/%s/%s", homedir, skelent->d_name); - lstat(src, &sb); - - if (sb.st_uid || sb.st_gid) { - warn("not creating %s due to ownership", dest); + int srcfd = open(src, O_RDONLY); + if (srcfd == -1) { + warnpe("open: %s", src); continue; } - if (S_ISREG(sb.st_mode)) { - int bytes; - char buf[4096]; - - int srcfd = open(src, O_RDONLY); - if (srcfd == -1) { - warnpe("open: %s", src); - continue; - } - - int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, sb.st_mode & 0777); - if (destfd == -1) { - warnpe("open: %s", dest); - close(srcfd); - continue; - } - - for (;;) { - bytes = read(srcfd, buf, sizeof(buf)); - if (!bytes) - break; - if (bytes < 0) { - warnpe("read"); - break; - } - if (write(destfd, buf, bytes) < 0) { - warnpe("write"); - break; - } - } - if (fchown(destfd, uid, gid)) - errorpe("chown: %s", dest); - + int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, sb.st_mode & 0777); + if (destfd == -1) { + warnpe("open: %s", dest); close(srcfd); - close(destfd); - } else if (S_ISDIR(sb.st_mode)) { - if (mkdir(dest, sb.st_mode & 0777)) { - warnpe("mkdir: %s", dest); - continue; - } - if (chown(dest, uid, gid)) - errorpe("chown: %s", dest); - } else if (S_ISLNK(sb.st_mode)) { - char lnkdest[PATH_MAX]; - int bytes; - bytes = readlink(src, lnkdest, sizeof(lnkdest)); - lnkdest[bytes] = '\0'; - if (bytes == -1) { - warnpe("readlink: %s", src); - continue; - } - if (symlink(lnkdest, dest)) { - warnpe("symlink: %s", dest); - continue; - } - if (lchown(dest, uid, gid)) - errorpe("lchown: %s", dest); - } else { - warn("not creating %s", dest); + continue; } - } - closedir(skel); + for (;;) { + bytes = read(srcfd, buf, sizeof(buf)); + if (!bytes) + break; + if (bytes < 0) { + warnpe("read"); + break; + } + if (write(destfd, buf, bytes) < 0) { + warnpe("write"); + break; + } + } + if (fchown(destfd, uid, gid)) + errorpe("chown: %s", dest); - if (chown(homedir, uid, gid)) { - errorpe("failed to chown %s", homedir); - return -1; + close(srcfd); + close(destfd); + } else if (S_ISDIR(sb.st_mode)) { + if (mkdir(dest, sb.st_mode & 0777)) { + warnpe("mkdir: %s", dest); + continue; + } + if (chown(dest, uid, gid)) + errorpe("chown: %s", dest); + } else if (S_ISLNK(sb.st_mode)) { + char lnkdest[PATH_MAX]; + int bytes; + bytes = readlink(src, lnkdest, sizeof(lnkdest)); + lnkdest[bytes] = '\0'; + if (bytes == -1) { + warnpe("readlink: %s", src); + continue; + } + if (symlink(lnkdest, dest)) { + warnpe("symlink: %s", dest); + continue; + } + if (lchown(dest, uid, gid)) + errorpe("lchown: %s", dest); + } else { + warn("not creating %s", dest); } } + closedir(skel); + + if (chown(homedir, uid, gid)) { + errorpe("failed to chown %s", homedir); + return -1; + } + return 0; } From 5ef116c4561bf875eff82f93f0e78e325fbcc2e8 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Thu, 23 Jul 2009 20:43:13 -0400 Subject: [PATCH 15/40] Add libsctp-dev to build dependencies --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 3661733..76f658f 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: ceo Section: admin Priority: optional Maintainer: Systems Committee -Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev +Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev, libsctp-dev Standards-Version: 3.7.2 Package: ceo From e5394d7729ef3de60da127d3f59ce114dd5266bf Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Fri, 24 Jul 2009 18:48:12 -0400 Subject: [PATCH 16/40] Make lintian happy --- debian/changelog | 6 ++++++ debian/control | 4 ++-- debian/rules | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 26398b3..e545cc2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ceo (0.4.10) stable testing; urgency=low + + * Bump standards version. + + -- Michael Spang Fri, 24 Jul 2009 18:47:33 -0400 + ceo (0.4.18) stable testing; urgency=low [ Michael Gregson ] diff --git a/debian/control b/debian/control index 76f658f..13ed7c5 100644 --- a/debian/control +++ b/debian/control @@ -2,8 +2,8 @@ Source: ceo Section: admin Priority: optional Maintainer: Systems Committee -Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev, libsctp-dev -Standards-Version: 3.7.2 +Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev, libsctp-dev, libprotobuf-c0-dev +Standards-Version: 3.8.2 Package: ceo Architecture: any diff --git a/debian/rules b/debian/rules index aca0a06..4a7303b 100755 --- a/debian/rules +++ b/debian/rules @@ -19,7 +19,7 @@ install: build dh_testroot dh_installdirs python setup.py -q install --no-compile -O0 --root=debian/ceo - $(MAKE) -C src DESTDIR=$(PWD)/debian/ceo PREFIX=/usr install + $(MAKE) -C src DESTDIR=$(CURDIR)/debian/ceo PREFIX=/usr install binary-arch: build install dh_testdir From 7c2f6459e6d88e19264332598a08ac86b906284d Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 25 Jul 2009 02:19:31 -0400 Subject: [PATCH 17/40] Add python-sqlobject to depends --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 13ed7c5..3de6a36 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,7 @@ Standards-Version: 3.8.2 Package: ceo Architecture: any -Depends: python-ldap, python-urwid, ${python:Depends}, ${shlibs:Depends} +Depends: python-ldap, python-urwid, python-sqlobject, ${python:Depends}, ${shlibs:Depends} Description: Computer Science Club Administrative Utilities This package contains the CSC Electronic Office and other Computer Science Club administrative From d6e6b2bc63b35aeceec365d26f5b7ca50398c888 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 25 Jul 2009 02:28:30 -0400 Subject: [PATCH 18/40] Add python-psycopg to depends --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 3de6a36..80500d3 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,7 @@ Standards-Version: 3.8.2 Package: ceo Architecture: any -Depends: python-ldap, python-urwid, python-sqlobject, ${python:Depends}, ${shlibs:Depends} +Depends: python-ldap, python-urwid, python-sqlobject, python-psycopg2, ${python:Depends}, ${shlibs:Depends} Description: Computer Science Club Administrative Utilities This package contains the CSC Electronic Office and other Computer Science Club administrative From 60e272e8c66b522d0957acfb52ab10443a8dbc32 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 25 Jul 2009 04:19:29 -0400 Subject: [PATCH 19/40] Remove keytab configuration Instead we'll always use the default keytab, which is /etc/krb5.keytab or the KRB5_KTNAME environment variable. --- src/config-vars.h | 3 --- src/kadm.c | 2 +- src/krb5.c | 10 +++------- src/krb5.h | 2 +- src/ldap.c | 4 ++-- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/config-vars.h b/src/config-vars.h index fa6c53b..2c2334c 100644 --- a/src/config-vars.h +++ b/src/config-vars.h @@ -25,9 +25,6 @@ CONFIG_STR(notify_hook) CONFIG_STR(realm) CONFIG_STR(admin_principal) -CONFIG_STR(admin_keytab) - CONFIG_STR(admin_bind_userid) -CONFIG_STR(admin_bind_keytab) CONFIG_STR(privileged_group) diff --git a/src/kadm.c b/src/kadm.c index 0fd05b6..3339e58 100644 --- a/src/kadm.c +++ b/src/kadm.c @@ -14,7 +14,7 @@ void ceo_kadm_init() { kadm5_config_params params; memset((void *) ¶ms, 0, sizeof(params)); - retval = kadm5_init_with_skey(admin_principal, admin_keytab, + retval = kadm5_init_with_skey(admin_principal, NULL /*admin_keytab */, KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &handle); if (retval) { diff --git a/src/krb5.c b/src/krb5.c index 31d07e5..5f4d4fc 100644 --- a/src/krb5.c +++ b/src/krb5.c @@ -1,4 +1,5 @@ #include + #include #include @@ -43,11 +44,10 @@ void ceo_krb5_init() { com_err(prog, retval, "while setting default realm"); } -void ceo_krb5_auth(char *principal, char *ktname) { +void ceo_krb5_auth(char *principal) { krb5_error_code retval; krb5_creds creds; krb5_principal princ; - krb5_keytab keytab; krb5_ccache cache; krb5_get_init_creds_opt options; @@ -60,10 +60,7 @@ void ceo_krb5_auth(char *principal, char *ktname) { if ((retval = krb5_cc_default(context, &cache))) com_err(prog, retval, "while resolving credentials cache"); - if ((retval = krb5_kt_resolve(context, ktname, &keytab))) - com_err(prog, retval, "while resolving keytab %s", admin_bind_keytab); - - if ((retval = krb5_get_init_creds_keytab(context, &creds, princ, keytab, 0, NULL, &options))) + if ((retval = krb5_get_init_creds_keytab(context, &creds, princ, NULL, 0, NULL, &options))) com_err(prog, retval, "while getting initial credentials"); if ((retval = krb5_cc_initialize(context, cache, princ))) @@ -73,7 +70,6 @@ void ceo_krb5_auth(char *principal, char *ktname) { com_err(prog, retval, "while storing credentials"); krb5_free_cred_contents(context, &creds); - krb5_kt_close(context, keytab); krb5_free_principal(context, princ); krb5_cc_close(context, cache); } diff --git a/src/krb5.h b/src/krb5.h index 9538b32..5877b79 100644 --- a/src/krb5.h +++ b/src/krb5.h @@ -8,7 +8,7 @@ extern krb5_context context; void ceo_krb5_init(); void ceo_krb5_cleanup(); -void ceo_krb5_auth(char *, char *); +void ceo_krb5_auth(char *); void ceo_krb5_deauth(); int ceo_read_password(char *, unsigned int, int); diff --git a/src/ldap.c b/src/ldap.c index dd7d34d..c318489 100644 --- a/src/ldap.c +++ b/src/ldap.c @@ -362,7 +362,7 @@ void ceo_ldap_init() { int proto = LDAP_DEFAULT_PROTOCOL; const char *sasl_mech = "GSSAPI"; - if (!admin_bind_userid || !admin_bind_keytab) + if (!admin_bind_userid) fatal("not configured"); if (ldap_initialize(&ld, server_url) != LDAP_SUCCESS) @@ -371,7 +371,7 @@ void ceo_ldap_init() { if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &proto) != LDAP_OPT_SUCCESS) ldap_fatal("ldap_set_option"); - ceo_krb5_auth(admin_bind_userid, admin_bind_keytab); + ceo_krb5_auth(admin_bind_userid); if (ldap_sasl_interactive_bind_s(ld, NULL, sasl_mech, NULL, NULL, LDAP_SASL_QUIET, &ldap_sasl_interact, NULL) != LDAP_SUCCESS) From e75390b7defc688dd3ff5abf11793a78389d52a3 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 25 Jul 2009 05:29:05 -0400 Subject: [PATCH 20/40] Fix networking bugs --- src/net.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/net.c b/src/net.c index f46e5c1..5bf3be7 100644 --- a/src/net.c +++ b/src/net.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "util.h" #include "net.h" @@ -32,7 +33,7 @@ void free_fqdn(void) { static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg, int *notification) { size_t len = 0; - int flags; + int flags = 0; int bytes; strbuf_reset(msg); @@ -43,8 +44,11 @@ static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strb bytes = sctp_recvmsg(sock, msg->buf + len, strbuf_avail(msg) - len, (sa *)&msg_meta->from, &msg_meta->fromlen, &msg_meta->sinfo, &flags); - if (bytes < 0) + if (bytes < 0) { + if (errno == EAGAIN) + continue; fatalpe("sctp_recvmsg"); + } if (!bytes) break; len += bytes; @@ -60,8 +64,15 @@ static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strb fatalpe("EOF in the middle of a message"); *notification = flags & MSG_NOTIFICATION; - if (*notification) + if (*notification) { notification_dbg(msg->buf); + union sctp_notification *sn = (union sctp_notification *) msg->buf; + switch (sn->sn_header.sn_type) { + case SCTP_SHUTDOWN_EVENT: + fatal("connection shut down"); + break; + } + } strbuf_setlen(msg, len); return len; From 0c828122ac743a43fd5d642a1a70fd105aff6e6c Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 25 Jul 2009 05:29:21 -0400 Subject: [PATCH 21/40] Make kerberos code more verbose --- src/kadm.c | 7 +++++++ src/krb5.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/kadm.c b/src/kadm.c index 3339e58..e2a1669 100644 --- a/src/kadm.c +++ b/src/kadm.c @@ -14,6 +14,8 @@ void ceo_kadm_init() { kadm5_config_params params; memset((void *) ¶ms, 0, sizeof(params)); + debug("kadmin: initializing using keytab for %s", admin_principal); + retval = kadm5_init_with_skey(admin_principal, NULL /*admin_keytab */, KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &handle); @@ -24,6 +26,7 @@ void ceo_kadm_init() { } void ceo_kadm_cleanup() { + debug("kadmin: cleaning up"); kadm5_destroy(handle); } @@ -32,6 +35,8 @@ int ceo_add_princ(char *user, char *password) { kadm5_principal_ent_rec princ; memset((void *) &princ, 0, sizeof(princ)); + debug("kadmin: adding principal %s", user); + if ((retval = krb5_parse_name(context, user, &princ.principal))) { com_err(prog, retval, "while parsing principal name"); return retval; @@ -50,6 +55,8 @@ int ceo_del_princ(char *user) { krb5_error_code retval; krb5_principal princ; + debug("kadmin: deleting principal %s", user); + if ((retval = krb5_parse_name(context, user, &princ))) { com_err(prog, retval, "while parsing principal name"); return retval; diff --git a/src/krb5.c b/src/krb5.c index 5f4d4fc..8fedade 100644 --- a/src/krb5.c +++ b/src/krb5.c @@ -35,6 +35,8 @@ void ceo_krb5_init() { set_com_err_hook(com_err_hk); + debug("krb5: initializing context"); + retval = krb5_init_context(&context); if (retval) com_err(prog, retval, "while initializing krb5"); @@ -54,6 +56,8 @@ void ceo_krb5_auth(char *principal) { krb5_get_init_creds_opt_init(&options); memset(&creds, 0, sizeof(creds)); + debug("krb5: getting TGT using keytab for %s", principal); + if ((retval = krb5_parse_name(context, principal, &princ))) com_err(prog, retval, "while resolving user %s", admin_bind_userid); @@ -78,6 +82,8 @@ void ceo_krb5_deauth() { krb5_error_code retval; krb5_ccache cache; + debug("krb5: destroying credentials"); + if ((retval = krb5_cc_default(context, &cache))) com_err(prog, retval, "while resolving credentials cache"); @@ -86,6 +92,7 @@ void ceo_krb5_deauth() { } void ceo_krb5_cleanup() { + debug("krb5: cleaning up"); krb5_free_context(context); } From bac4db4f4d56619f4e995ad75cb9fc462170b7d8 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 25 Jul 2009 05:29:37 -0400 Subject: [PATCH 22/40] Fail op handling if unathenticated --- src/dslave.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dslave.c b/src/dslave.c index f62e0a5..dd373cf 100644 --- a/src/dslave.c +++ b/src/dslave.c @@ -89,6 +89,10 @@ static void handle_op_message(uint32_t in_type, struct strbuf *in, struct strbuf if (!op->name) fatal("operation %x does not exist", in_type); + /* TEMPORARY */ + if (!client_username()) + fatal("unathenticated"); + make_env(envp, "LANG", "C", "CEO_USER", client_username(), "CEO_CONFIG_DIR", config_dir, NULL); char *argv[] = { op->path, NULL, }; From 4ede8212d51ed3fd9c70552f2a13927da8f2ac8d Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 25 Jul 2009 05:31:17 -0400 Subject: [PATCH 23/40] Require TGT in ldap_init --- src/ldap.c | 4 ---- src/op-adduser.c | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ldap.c b/src/ldap.c index c318489..4c269d6 100644 --- a/src/ldap.c +++ b/src/ldap.c @@ -371,13 +371,9 @@ void ceo_ldap_init() { if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &proto) != LDAP_OPT_SUCCESS) ldap_fatal("ldap_set_option"); - ceo_krb5_auth(admin_bind_userid); - if (ldap_sasl_interactive_bind_s(ld, NULL, sasl_mech, NULL, NULL, LDAP_SASL_QUIET, &ldap_sasl_interact, NULL) != LDAP_SUCCESS) ldap_fatal("Bind failed"); - - ceo_krb5_deauth(); } void ceo_ldap_cleanup() { diff --git a/src/op-adduser.c b/src/op-adduser.c index 0d54508..c75f8bb 100644 --- a/src/op-adduser.c +++ b/src/op-adduser.c @@ -270,6 +270,7 @@ int main(int argc, char *argv[]) { fatalpe("setenv"); ceo_krb5_init(); + ceo_krb5_auth(admin_bind_userid); ceo_ldap_init(); ceo_kadm_init(); @@ -277,6 +278,7 @@ int main(int argc, char *argv[]) { ceo_kadm_cleanup(); ceo_ldap_cleanup(); + ceo_krb5_deauth(); ceo_krb5_cleanup(); free_config(); From 25646ac593404db40ddd7490e3e1ef91599be48d Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 25 Jul 2009 05:46:09 -0400 Subject: [PATCH 24/40] Remove kadmin headers --- include/kadm5/adb_err.h | 36 -- include/kadm5/admin.h | 733 ---------------------------- include/kadm5/chpass_util_strings.h | 38 -- include/kadm5/kadm_err.h | 77 --- include/kadm5/kadm_rpc.h | 335 ------------- include/kdb.h | 334 ------------- src/Makefile | 2 +- 7 files changed, 1 insertion(+), 1554 deletions(-) delete mode 100644 include/kadm5/adb_err.h delete mode 100644 include/kadm5/admin.h delete mode 100644 include/kadm5/chpass_util_strings.h delete mode 100644 include/kadm5/kadm_err.h delete mode 100644 include/kadm5/kadm_rpc.h delete mode 100644 include/kdb.h diff --git a/include/kadm5/adb_err.h b/include/kadm5/adb_err.h deleted file mode 100644 index e018099..0000000 --- a/include/kadm5/adb_err.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ettmp27965.h: - * This file is automatically generated; please do not edit it. - */ - -#include - -#define OSA_ADB_NOERR (28810240L) -#define OSA_ADB_DUP (28810241L) -#define OSA_ADB_NOENT (28810242L) -#define OSA_ADB_DBINIT (28810243L) -#define OSA_ADB_BAD_POLICY (28810244L) -#define OSA_ADB_BAD_PRINC (28810245L) -#define OSA_ADB_BAD_DB (28810246L) -#define OSA_ADB_XDR_FAILURE (28810247L) -#define OSA_ADB_FAILURE (28810248L) -#define OSA_ADB_BADLOCKMODE (28810249L) -#define OSA_ADB_CANTLOCK_DB (28810250L) -#define OSA_ADB_NOTLOCKED (28810251L) -#define OSA_ADB_NOLOCKFILE (28810252L) -#define OSA_ADB_NOEXCL_PERM (28810253L) -#define ERROR_TABLE_BASE_adb (28810240L) - -extern const struct error_table et_adb_error_table; - -#if !defined(_WIN32) -/* for compatibility with older versions... */ -extern void initialize_adb_error_table (void) /*@modifies internalState@*/; -#else -#define initialize_adb_error_table() -#endif - -#if !defined(_WIN32) -#define init_adb_err_tbl initialize_adb_error_table -#define adb_err_base ERROR_TABLE_BASE_adb -#endif diff --git a/include/kadm5/admin.h b/include/kadm5/admin.h deleted file mode 100644 index bde7846..0000000 --- a/include/kadm5/admin.h +++ /dev/null @@ -1,733 +0,0 @@ -/* - * lib/kadm5/admin.h - * - * Copyright 2001 by the Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - */ -/* - * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved - * - * $Header$ - */ - -#ifndef __KADM5_ADMIN_H__ -#define __KADM5_ADMIN_H__ - -#if !defined(USE_KADM5_API_VERSION) -#define USE_KADM5_API_VERSION 2 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#define KADM5_ADMIN_SERVICE "kadmin/admin" -#define KADM5_CHANGEPW_SERVICE "kadmin/changepw" -#define KADM5_HIST_PRINCIPAL "kadmin/history" - -typedef krb5_principal kadm5_princ_t; -typedef char *kadm5_policy_t; -typedef long kadm5_ret_t; - -#define KADM5_PW_FIRST_PROMPT \ - (error_message(CHPASS_UTIL_NEW_PASSWORD_PROMPT)) -#define KADM5_PW_SECOND_PROMPT \ - (error_message(CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT)) - -/* - * Successful return code - */ -#define KADM5_OK 0 - -/* - * Field masks - */ - -/* kadm5_principal_ent_t */ -#define KADM5_PRINCIPAL 0x000001 -#define KADM5_PRINC_EXPIRE_TIME 0x000002 -#define KADM5_PW_EXPIRATION 0x000004 -#define KADM5_LAST_PWD_CHANGE 0x000008 -#define KADM5_ATTRIBUTES 0x000010 -#define KADM5_MAX_LIFE 0x000020 -#define KADM5_MOD_TIME 0x000040 -#define KADM5_MOD_NAME 0x000080 -#define KADM5_KVNO 0x000100 -#define KADM5_MKVNO 0x000200 -#define KADM5_AUX_ATTRIBUTES 0x000400 -#define KADM5_POLICY 0x000800 -#define KADM5_POLICY_CLR 0x001000 -/* version 2 masks */ -#define KADM5_MAX_RLIFE 0x002000 -#define KADM5_LAST_SUCCESS 0x004000 -#define KADM5_LAST_FAILED 0x008000 -#define KADM5_FAIL_AUTH_COUNT 0x010000 -#define KADM5_KEY_DATA 0x020000 -#define KADM5_TL_DATA 0x040000 -/* all but KEY_DATA and TL_DATA */ -#define KADM5_PRINCIPAL_NORMAL_MASK 0x01ffff - -/* kadm5_policy_ent_t */ -#define KADM5_PW_MAX_LIFE 0x004000 -#define KADM5_PW_MIN_LIFE 0x008000 -#define KADM5_PW_MIN_LENGTH 0x010000 -#define KADM5_PW_MIN_CLASSES 0x020000 -#define KADM5_PW_HISTORY_NUM 0x040000 -#define KADM5_REF_COUNT 0x080000 - -/* kadm5_config_params */ -#define KADM5_CONFIG_REALM 0x000001 -#define KADM5_CONFIG_DBNAME 0x000002 -#define KADM5_CONFIG_MKEY_NAME 0x000004 -#define KADM5_CONFIG_MAX_LIFE 0x000008 -#define KADM5_CONFIG_MAX_RLIFE 0x000010 -#define KADM5_CONFIG_EXPIRATION 0x000020 -#define KADM5_CONFIG_FLAGS 0x000040 -#define KADM5_CONFIG_ADMIN_KEYTAB 0x000080 -#define KADM5_CONFIG_STASH_FILE 0x000100 -#define KADM5_CONFIG_ENCTYPE 0x000200 -#define KADM5_CONFIG_ADBNAME 0x000400 -#define KADM5_CONFIG_ADB_LOCKFILE 0x000800 -#define KADM5_CONFIG_PROFILE 0x001000 -#define KADM5_CONFIG_ACL_FILE 0x002000 -#define KADM5_CONFIG_KADMIND_PORT 0x004000 -#define KADM5_CONFIG_ENCTYPES 0x008000 -#define KADM5_CONFIG_ADMIN_SERVER 0x010000 -#define KADM5_CONFIG_DICT_FILE 0x020000 -#define KADM5_CONFIG_MKEY_FROM_KBD 0x040000 -#define KADM5_CONFIG_KPASSWD_PORT 0x080000 -#define KADM5_CONFIG_OLD_AUTH_GSSAPI 0x100000 -#define KADM5_CONFIG_NO_AUTH 0x200000 -#define KADM5_CONFIG_AUTH_NOFALLBACK 0x400000 - -/* - * permission bits - */ -#define KADM5_PRIV_GET 0x01 -#define KADM5_PRIV_ADD 0x02 -#define KADM5_PRIV_MODIFY 0x04 -#define KADM5_PRIV_DELETE 0x08 - -/* - * API versioning constants - */ -#define KADM5_MASK_BITS 0xffffff00 - -#define KADM5_STRUCT_VERSION_MASK 0x12345600 -#define KADM5_STRUCT_VERSION_1 (KADM5_STRUCT_VERSION_MASK|0x01) -#define KADM5_STRUCT_VERSION KADM5_STRUCT_VERSION_1 - -#define KADM5_API_VERSION_MASK 0x12345700 -#define KADM5_API_VERSION_1 (KADM5_API_VERSION_MASK|0x01) -#define KADM5_API_VERSION_2 (KADM5_API_VERSION_MASK|0x02) - -typedef struct _kadm5_principal_ent_t_v2 { - krb5_principal principal; - krb5_timestamp princ_expire_time; - krb5_timestamp last_pwd_change; - krb5_timestamp pw_expiration; - krb5_deltat max_life; - krb5_principal mod_name; - krb5_timestamp mod_date; - krb5_flags attributes; - krb5_kvno kvno; - krb5_kvno mkvno; - char *policy; - long aux_attributes; - - /* version 2 fields */ - krb5_deltat max_renewable_life; - krb5_timestamp last_success; - krb5_timestamp last_failed; - krb5_kvno fail_auth_count; - krb5_int16 n_key_data; - krb5_int16 n_tl_data; - krb5_tl_data *tl_data; - krb5_key_data *key_data; -} kadm5_principal_ent_rec_v2, *kadm5_principal_ent_t_v2; - -typedef struct _kadm5_principal_ent_t_v1 { - krb5_principal principal; - krb5_timestamp princ_expire_time; - krb5_timestamp last_pwd_change; - krb5_timestamp pw_expiration; - krb5_deltat max_life; - krb5_principal mod_name; - krb5_timestamp mod_date; - krb5_flags attributes; - krb5_kvno kvno; - krb5_kvno mkvno; - char *policy; - long aux_attributes; -} kadm5_principal_ent_rec_v1, *kadm5_principal_ent_t_v1; - -#if USE_KADM5_API_VERSION == 1 -typedef struct _kadm5_principal_ent_t_v1 - kadm5_principal_ent_rec, *kadm5_principal_ent_t; -#else -typedef struct _kadm5_principal_ent_t_v2 - kadm5_principal_ent_rec, *kadm5_principal_ent_t; -#endif - -typedef struct _kadm5_policy_ent_t { - char *policy; - long pw_min_life; - long pw_max_life; - long pw_min_length; - long pw_min_classes; - long pw_history_num; - long policy_refcnt; -} kadm5_policy_ent_rec, *kadm5_policy_ent_t; - -typedef struct __krb5_key_salt_tuple { - krb5_enctype ks_enctype; - krb5_int32 ks_salttype; -} krb5_key_salt_tuple; - -/* - * Data structure returned by kadm5_get_config_params() - */ -typedef struct _kadm5_config_params { - long mask; - char * realm; - char * profile; - int kadmind_port; - int kpasswd_port; - - char * admin_server; - - char * dbname; - char * admin_dbname; - char * admin_lockfile; - char * admin_keytab; - char * acl_file; - char * dict_file; - - int mkey_from_kbd; - char * stash_file; - char * mkey_name; - krb5_enctype enctype; - krb5_deltat max_life; - krb5_deltat max_rlife; - krb5_timestamp expiration; - krb5_flags flags; - krb5_key_salt_tuple *keysalts; - krb5_int32 num_keysalts; -} kadm5_config_params; - -/*********************************************************************** - * This is the old krb5_realm_read_params, which I mutated into - * kadm5_get_config_params but which old code (kdb5_* and krb5kdc) - * still uses. - ***********************************************************************/ - -/* - * Data structure returned by krb5_read_realm_params() - */ -typedef struct __krb5_realm_params { - char * realm_profile; - char * realm_dbname; - char * realm_mkey_name; - char * realm_stash_file; - char * realm_kdc_ports; - char * realm_kdc_tcp_ports; - char * realm_acl_file; - krb5_int32 realm_kadmind_port; - krb5_enctype realm_enctype; - krb5_deltat realm_max_life; - krb5_deltat realm_max_rlife; - krb5_timestamp realm_expiration; - krb5_flags realm_flags; - krb5_key_salt_tuple *realm_keysalts; - unsigned int realm_reject_bad_transit:1; - unsigned int realm_kadmind_port_valid:1; - unsigned int realm_enctype_valid:1; - unsigned int realm_max_life_valid:1; - unsigned int realm_max_rlife_valid:1; - unsigned int realm_expiration_valid:1; - unsigned int realm_flags_valid:1; - unsigned int realm_reject_bad_transit_valid:1; - krb5_int32 realm_num_keysalts; -} krb5_realm_params; - -/* - * functions - */ - -#if USE_KADM5_API_VERSION > 1 -krb5_error_code kadm5_get_config_params(krb5_context context, - char *kdcprofile, char *kdcenv, - kadm5_config_params *params_in, - kadm5_config_params *params_out); - -krb5_error_code kadm5_free_config_params(krb5_context context, - kadm5_config_params *params); - -krb5_error_code kadm5_free_realm_params(krb5_context kcontext, - kadm5_config_params *params); - -krb5_error_code kadm5_get_admin_service_name(krb5_context, char *, - char *, size_t); -#endif - -kadm5_ret_t kadm5_init(char *client_name, char *pass, - char *service_name, -#if USE_KADM5_API_VERSION == 1 - char *realm, -#else - kadm5_config_params *params, -#endif - krb5_ui_4 struct_version, - krb5_ui_4 api_version, - void **server_handle); -kadm5_ret_t kadm5_init_with_password(char *client_name, - char *pass, - char *service_name, -#if USE_KADM5_API_VERSION == 1 - char *realm, -#else - kadm5_config_params *params, -#endif - krb5_ui_4 struct_version, - krb5_ui_4 api_version, - void **server_handle); -kadm5_ret_t kadm5_init_with_skey(char *client_name, - char *keytab, - char *service_name, -#if USE_KADM5_API_VERSION == 1 - char *realm, -#else - kadm5_config_params *params, -#endif - krb5_ui_4 struct_version, - krb5_ui_4 api_version, - void **server_handle); -#if USE_KADM5_API_VERSION > 1 -kadm5_ret_t kadm5_init_with_creds(char *client_name, - krb5_ccache cc, - char *service_name, - kadm5_config_params *params, - krb5_ui_4 struct_version, - krb5_ui_4 api_version, - void **server_handle); -#endif -kadm5_ret_t kadm5_lock(void *server_handle); -kadm5_ret_t kadm5_unlock(void *server_handle); -kadm5_ret_t kadm5_flush(void *server_handle); -kadm5_ret_t kadm5_destroy(void *server_handle); -kadm5_ret_t kadm5_create_principal(void *server_handle, - kadm5_principal_ent_t ent, - long mask, char *pass); -kadm5_ret_t kadm5_create_principal_3(void *server_handle, - kadm5_principal_ent_t ent, - long mask, - int n_ks_tuple, - krb5_key_salt_tuple *ks_tuple, - char *pass); -kadm5_ret_t kadm5_delete_principal(void *server_handle, - krb5_principal principal); -kadm5_ret_t kadm5_modify_principal(void *server_handle, - kadm5_principal_ent_t ent, - long mask); -kadm5_ret_t kadm5_rename_principal(void *server_handle, - krb5_principal,krb5_principal); -#if USE_KADM5_API_VERSION == 1 -kadm5_ret_t kadm5_get_principal(void *server_handle, - krb5_principal principal, - kadm5_principal_ent_t *ent); -#else -kadm5_ret_t kadm5_get_principal(void *server_handle, - krb5_principal principal, - kadm5_principal_ent_t ent, - long mask); -#endif -kadm5_ret_t kadm5_chpass_principal(void *server_handle, - krb5_principal principal, - char *pass); -kadm5_ret_t kadm5_chpass_principal_3(void *server_handle, - krb5_principal principal, - krb5_boolean keepold, - int n_ks_tuple, - krb5_key_salt_tuple *ks_tuple, - char *pass); -#if USE_KADM5_API_VERSION == 1 -kadm5_ret_t kadm5_randkey_principal(void *server_handle, - krb5_principal principal, - krb5_keyblock **keyblock); -#else -kadm5_ret_t kadm5_randkey_principal(void *server_handle, - krb5_principal principal, - krb5_keyblock **keyblocks, - int *n_keys); -kadm5_ret_t kadm5_randkey_principal_3(void *server_handle, - krb5_principal principal, - krb5_boolean keepold, - int n_ks_tuple, - krb5_key_salt_tuple *ks_tuple, - krb5_keyblock **keyblocks, - int *n_keys); -#endif -kadm5_ret_t kadm5_setv4key_principal(void *server_handle, - krb5_principal principal, - krb5_keyblock *keyblock); - -kadm5_ret_t kadm5_setkey_principal(void *server_handle, - krb5_principal principal, - krb5_keyblock *keyblocks, - int n_keys); - -kadm5_ret_t kadm5_setkey_principal_3(void *server_handle, - krb5_principal principal, - krb5_boolean keepold, - int n_ks_tuple, - krb5_key_salt_tuple *ks_tuple, - krb5_keyblock *keyblocks, - int n_keys); - -kadm5_ret_t kadm5_decrypt_key(void *server_handle, - kadm5_principal_ent_t entry, krb5_int32 - ktype, krb5_int32 stype, krb5_int32 - kvno, krb5_keyblock *keyblock, - krb5_keysalt *keysalt, int *kvnop); - -kadm5_ret_t kadm5_create_policy(void *server_handle, - kadm5_policy_ent_t ent, - long mask); -/* - * kadm5_create_policy_internal is not part of the supported, - * exposed API. It is available only in the server library, and you - * shouldn't use it unless you know why it's there and how it's - * different from kadm5_create_policy. - */ -kadm5_ret_t kadm5_create_policy_internal(void *server_handle, - kadm5_policy_ent_t - entry, long mask); -kadm5_ret_t kadm5_delete_policy(void *server_handle, - kadm5_policy_t policy); -kadm5_ret_t kadm5_modify_policy(void *server_handle, - kadm5_policy_ent_t ent, - long mask); -/* - * kadm5_modify_policy_internal is not part of the supported, - * exposed API. It is available only in the server library, and you - * shouldn't use it unless you know why it's there and how it's - * different from kadm5_modify_policy. - */ -kadm5_ret_t kadm5_modify_policy_internal(void *server_handle, - kadm5_policy_ent_t - entry, long mask); -#if USE_KADM5_API_VERSION == 1 -kadm5_ret_t kadm5_get_policy(void *server_handle, - kadm5_policy_t policy, - kadm5_policy_ent_t *ent); -#else -kadm5_ret_t kadm5_get_policy(void *server_handle, - kadm5_policy_t policy, - kadm5_policy_ent_t ent); -#endif -kadm5_ret_t kadm5_get_privs(void *server_handle, - long *privs); - -kadm5_ret_t kadm5_chpass_principal_util(void *server_handle, - krb5_principal princ, - char *new_pw, - char **ret_pw, - char *msg_ret, - unsigned int msg_len); - -kadm5_ret_t kadm5_free_principal_ent(void *server_handle, - kadm5_principal_ent_t - ent); -kadm5_ret_t kadm5_free_policy_ent(void *server_handle, - kadm5_policy_ent_t ent); - -kadm5_ret_t kadm5_get_principals(void *server_handle, - char *exp, char ***princs, - int *count); - -kadm5_ret_t kadm5_get_policies(void *server_handle, - char *exp, char ***pols, - int *count); - -#if USE_KADM5_API_VERSION > 1 -kadm5_ret_t kadm5_free_key_data(void *server_handle, - krb5_int16 *n_key_data, - krb5_key_data *key_data); -#endif - -kadm5_ret_t kadm5_free_name_list(void *server_handle, char **names, - int count); - -#if USE_KADM5_API_VERSION == 1 -/* - * OVSEC_KADM_API_VERSION_1 should be, if possible, compile-time - * compatible with KADM5_API_VERSION_2. Basically, this means we have - * to continue to provide all the old ovsec_kadm function and symbol - * names. - */ - -#define OVSEC_KADM_ACLFILE "/krb5/ovsec_adm.acl" -#define OVSEC_KADM_WORDFILE "/krb5/ovsec_adm.dict" - -#define OVSEC_KADM_ADMIN_SERVICE "ovsec_adm/admin" -#define OVSEC_KADM_CHANGEPW_SERVICE "ovsec_adm/changepw" -#define OVSEC_KADM_HIST_PRINCIPAL "ovsec_adm/history" - -typedef krb5_principal ovsec_kadm_princ_t; -typedef krb5_keyblock ovsec_kadm_keyblock; -typedef char *ovsec_kadm_policy_t; -typedef long ovsec_kadm_ret_t; - -enum ovsec_kadm_salttype { OVSEC_KADM_SALT_V4, OVSEC_KADM_SALT_NORMAL }; -enum ovsec_kadm_saltmod { OVSEC_KADM_MOD_KEEP, OVSEC_KADM_MOD_V4, OVSEC_KADM_MOD_NORMAL }; - -#define OVSEC_KADM_PW_FIRST_PROMPT \ - ((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_PROMPT)) -#define OVSEC_KADM_PW_SECOND_PROMPT \ - ((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT)) - -/* - * Successful return code - */ -#define OVSEC_KADM_OK 0 - -/* - * Create/Modify masks - */ -/* principal */ -#define OVSEC_KADM_PRINCIPAL 0x000001 -#define OVSEC_KADM_PRINC_EXPIRE_TIME 0x000002 -#define OVSEC_KADM_PW_EXPIRATION 0x000004 -#define OVSEC_KADM_LAST_PWD_CHANGE 0x000008 -#define OVSEC_KADM_ATTRIBUTES 0x000010 -#define OVSEC_KADM_MAX_LIFE 0x000020 -#define OVSEC_KADM_MOD_TIME 0x000040 -#define OVSEC_KADM_MOD_NAME 0x000080 -#define OVSEC_KADM_KVNO 0x000100 -#define OVSEC_KADM_MKVNO 0x000200 -#define OVSEC_KADM_AUX_ATTRIBUTES 0x000400 -#define OVSEC_KADM_POLICY 0x000800 -#define OVSEC_KADM_POLICY_CLR 0x001000 -/* policy */ -#define OVSEC_KADM_PW_MAX_LIFE 0x004000 -#define OVSEC_KADM_PW_MIN_LIFE 0x008000 -#define OVSEC_KADM_PW_MIN_LENGTH 0x010000 -#define OVSEC_KADM_PW_MIN_CLASSES 0x020000 -#define OVSEC_KADM_PW_HISTORY_NUM 0x040000 -#define OVSEC_KADM_REF_COUNT 0x080000 - -/* - * permission bits - */ -#define OVSEC_KADM_PRIV_GET 0x01 -#define OVSEC_KADM_PRIV_ADD 0x02 -#define OVSEC_KADM_PRIV_MODIFY 0x04 -#define OVSEC_KADM_PRIV_DELETE 0x08 - -/* - * API versioning constants - */ -#define OVSEC_KADM_MASK_BITS 0xffffff00 - -#define OVSEC_KADM_STRUCT_VERSION_MASK 0x12345600 -#define OVSEC_KADM_STRUCT_VERSION_1 (OVSEC_KADM_STRUCT_VERSION_MASK|0x01) -#define OVSEC_KADM_STRUCT_VERSION OVSEC_KADM_STRUCT_VERSION_1 - -#define OVSEC_KADM_API_VERSION_MASK 0x12345700 -#define OVSEC_KADM_API_VERSION_1 (OVSEC_KADM_API_VERSION_MASK|0x01) - - -typedef struct _ovsec_kadm_principal_ent_t { - krb5_principal principal; - krb5_timestamp princ_expire_time; - krb5_timestamp last_pwd_change; - krb5_timestamp pw_expiration; - krb5_deltat max_life; - krb5_principal mod_name; - krb5_timestamp mod_date; - krb5_flags attributes; - krb5_kvno kvno; - krb5_kvno mkvno; - char *policy; - long aux_attributes; -} ovsec_kadm_principal_ent_rec, *ovsec_kadm_principal_ent_t; - -typedef struct _ovsec_kadm_policy_ent_t { - char *policy; - long pw_min_life; - long pw_max_life; - long pw_min_length; - long pw_min_classes; - long pw_history_num; - long policy_refcnt; -} ovsec_kadm_policy_ent_rec, *ovsec_kadm_policy_ent_t; - -/* - * functions - */ -ovsec_kadm_ret_t ovsec_kadm_init(char *client_name, char *pass, - char *service_name, char *realm, - krb5_ui_4 struct_version, - krb5_ui_4 api_version, - void **server_handle); -ovsec_kadm_ret_t ovsec_kadm_init_with_password(char *client_name, - char *pass, - char *service_name, - char *realm, - krb5_ui_4 struct_version, - krb5_ui_4 api_version, - void **server_handle); -ovsec_kadm_ret_t ovsec_kadm_init_with_skey(char *client_name, - char *keytab, - char *service_name, - char *realm, - krb5_ui_4 struct_version, - krb5_ui_4 api_version, - void **server_handle); -ovsec_kadm_ret_t ovsec_kadm_flush(void *server_handle); -ovsec_kadm_ret_t ovsec_kadm_destroy(void *server_handle); -ovsec_kadm_ret_t ovsec_kadm_create_principal(void *server_handle, - ovsec_kadm_principal_ent_t ent, - long mask, char *pass); -ovsec_kadm_ret_t ovsec_kadm_delete_principal(void *server_handle, - krb5_principal principal); -ovsec_kadm_ret_t ovsec_kadm_modify_principal(void *server_handle, - ovsec_kadm_principal_ent_t ent, - long mask); -ovsec_kadm_ret_t ovsec_kadm_rename_principal(void *server_handle, - krb5_principal,krb5_principal); -ovsec_kadm_ret_t ovsec_kadm_get_principal(void *server_handle, - krb5_principal principal, - ovsec_kadm_principal_ent_t *ent); -ovsec_kadm_ret_t ovsec_kadm_chpass_principal(void *server_handle, - krb5_principal principal, - char *pass); -ovsec_kadm_ret_t ovsec_kadm_randkey_principal(void *server_handle, - krb5_principal principal, - krb5_keyblock **keyblock); -ovsec_kadm_ret_t ovsec_kadm_create_policy(void *server_handle, - ovsec_kadm_policy_ent_t ent, - long mask); -/* - * ovsec_kadm_create_policy_internal is not part of the supported, - * exposed API. It is available only in the server library, and you - * shouldn't use it unless you know why it's there and how it's - * different from ovsec_kadm_create_policy. - */ -ovsec_kadm_ret_t ovsec_kadm_create_policy_internal(void *server_handle, - ovsec_kadm_policy_ent_t - entry, long mask); -ovsec_kadm_ret_t ovsec_kadm_delete_policy(void *server_handle, - ovsec_kadm_policy_t policy); -ovsec_kadm_ret_t ovsec_kadm_modify_policy(void *server_handle, - ovsec_kadm_policy_ent_t ent, - long mask); -/* - * ovsec_kadm_modify_policy_internal is not part of the supported, - * exposed API. It is available only in the server library, and you - * shouldn't use it unless you know why it's there and how it's - * different from ovsec_kadm_modify_policy. - */ -ovsec_kadm_ret_t ovsec_kadm_modify_policy_internal(void *server_handle, - ovsec_kadm_policy_ent_t - entry, long mask); -ovsec_kadm_ret_t ovsec_kadm_get_policy(void *server_handle, - ovsec_kadm_policy_t policy, - ovsec_kadm_policy_ent_t *ent); -ovsec_kadm_ret_t ovsec_kadm_get_privs(void *server_handle, - long *privs); - -ovsec_kadm_ret_t ovsec_kadm_chpass_principal_util(void *server_handle, - krb5_principal princ, - char *new_pw, - char **ret_pw, - char *msg_ret); - -ovsec_kadm_ret_t ovsec_kadm_free_principal_ent(void *server_handle, - ovsec_kadm_principal_ent_t - ent); -ovsec_kadm_ret_t ovsec_kadm_free_policy_ent(void *server_handle, - ovsec_kadm_policy_ent_t ent); - -ovsec_kadm_ret_t ovsec_kadm_free_name_list(void *server_handle, - char **names, int count); - -ovsec_kadm_ret_t ovsec_kadm_get_principals(void *server_handle, - char *exp, char ***princs, - int *count); - -ovsec_kadm_ret_t ovsec_kadm_get_policies(void *server_handle, - char *exp, char ***pols, - int *count); - -#define OVSEC_KADM_FAILURE KADM5_FAILURE -#define OVSEC_KADM_AUTH_GET KADM5_AUTH_GET -#define OVSEC_KADM_AUTH_ADD KADM5_AUTH_ADD -#define OVSEC_KADM_AUTH_MODIFY KADM5_AUTH_MODIFY -#define OVSEC_KADM_AUTH_DELETE KADM5_AUTH_DELETE -#define OVSEC_KADM_AUTH_INSUFFICIENT KADM5_AUTH_INSUFFICIENT -#define OVSEC_KADM_BAD_DB KADM5_BAD_DB -#define OVSEC_KADM_DUP KADM5_DUP -#define OVSEC_KADM_RPC_ERROR KADM5_RPC_ERROR -#define OVSEC_KADM_NO_SRV KADM5_NO_SRV -#define OVSEC_KADM_BAD_HIST_KEY KADM5_BAD_HIST_KEY -#define OVSEC_KADM_NOT_INIT KADM5_NOT_INIT -#define OVSEC_KADM_UNK_PRINC KADM5_UNK_PRINC -#define OVSEC_KADM_UNK_POLICY KADM5_UNK_POLICY -#define OVSEC_KADM_BAD_MASK KADM5_BAD_MASK -#define OVSEC_KADM_BAD_CLASS KADM5_BAD_CLASS -#define OVSEC_KADM_BAD_LENGTH KADM5_BAD_LENGTH -#define OVSEC_KADM_BAD_POLICY KADM5_BAD_POLICY -#define OVSEC_KADM_BAD_PRINCIPAL KADM5_BAD_PRINCIPAL -#define OVSEC_KADM_BAD_AUX_ATTR KADM5_BAD_AUX_ATTR -#define OVSEC_KADM_BAD_HISTORY KADM5_BAD_HISTORY -#define OVSEC_KADM_BAD_MIN_PASS_LIFE KADM5_BAD_MIN_PASS_LIFE -#define OVSEC_KADM_PASS_Q_TOOSHORT KADM5_PASS_Q_TOOSHORT -#define OVSEC_KADM_PASS_Q_CLASS KADM5_PASS_Q_CLASS -#define OVSEC_KADM_PASS_Q_DICT KADM5_PASS_Q_DICT -#define OVSEC_KADM_PASS_REUSE KADM5_PASS_REUSE -#define OVSEC_KADM_PASS_TOOSOON KADM5_PASS_TOOSOON -#define OVSEC_KADM_POLICY_REF KADM5_POLICY_REF -#define OVSEC_KADM_INIT KADM5_INIT -#define OVSEC_KADM_BAD_PASSWORD KADM5_BAD_PASSWORD -#define OVSEC_KADM_PROTECT_PRINCIPAL KADM5_PROTECT_PRINCIPAL -#define OVSEC_KADM_BAD_SERVER_HANDLE KADM5_BAD_SERVER_HANDLE -#define OVSEC_KADM_BAD_STRUCT_VERSION KADM5_BAD_STRUCT_VERSION -#define OVSEC_KADM_OLD_STRUCT_VERSION KADM5_OLD_STRUCT_VERSION -#define OVSEC_KADM_NEW_STRUCT_VERSION KADM5_NEW_STRUCT_VERSION -#define OVSEC_KADM_BAD_API_VERSION KADM5_BAD_API_VERSION -#define OVSEC_KADM_OLD_LIB_API_VERSION KADM5_OLD_LIB_API_VERSION -#define OVSEC_KADM_OLD_SERVER_API_VERSION KADM5_OLD_SERVER_API_VERSION -#define OVSEC_KADM_NEW_LIB_API_VERSION KADM5_NEW_LIB_API_VERSION -#define OVSEC_KADM_NEW_SERVER_API_VERSION KADM5_NEW_SERVER_API_VERSION -#define OVSEC_KADM_SECURE_PRINC_MISSING KADM5_SECURE_PRINC_MISSING -#define OVSEC_KADM_NO_RENAME_SALT KADM5_NO_RENAME_SALT - -#endif /* USE_KADM5_API_VERSION == 1 */ - -#endif /* __KADM5_ADMIN_H__ */ diff --git a/include/kadm5/chpass_util_strings.h b/include/kadm5/chpass_util_strings.h deleted file mode 100644 index cddd285..0000000 --- a/include/kadm5/chpass_util_strings.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * ettmp27966.h: - * This file is automatically generated; please do not edit it. - */ - -#include - -#define CHPASS_UTIL_GET_POLICY_INFO (-1492553984L) -#define CHPASS_UTIL_GET_PRINC_INFO (-1492553983L) -#define CHPASS_UTIL_NEW_PASSWORD_MISMATCH (-1492553982L) -#define CHPASS_UTIL_NEW_PASSWORD_PROMPT (-1492553981L) -#define CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT (-1492553980L) -#define CHPASS_UTIL_NO_PASSWORD_READ (-1492553979L) -#define CHPASS_UTIL_NO_POLICY_YET_Q_ERROR (-1492553978L) -#define CHPASS_UTIL_PASSWORD_CHANGED (-1492553977L) -#define CHPASS_UTIL_PASSWORD_IN_DICTIONARY (-1492553976L) -#define CHPASS_UTIL_PASSWORD_NOT_CHANGED (-1492553975L) -#define CHPASS_UTIL_PASSWORD_TOO_SHORT (-1492553974L) -#define CHPASS_UTIL_TOO_FEW_CLASSES (-1492553973L) -#define CHPASS_UTIL_PASSWORD_TOO_SOON (-1492553972L) -#define CHPASS_UTIL_PASSWORD_REUSE (-1492553971L) -#define CHPASS_UTIL_WHILE_TRYING_TO_CHANGE (-1492553970L) -#define CHPASS_UTIL_WHILE_READING_PASSWORD (-1492553969L) -#define ERROR_TABLE_BASE_ovku (-1492553984L) - -extern const struct error_table et_ovku_error_table; - -#if !defined(_WIN32) -/* for compatibility with older versions... */ -extern void initialize_ovku_error_table (void) /*@modifies internalState@*/; -#else -#define initialize_ovku_error_table() -#endif - -#if !defined(_WIN32) -#define init_ovku_err_tbl initialize_ovku_error_table -#define ovku_err_base ERROR_TABLE_BASE_ovku -#endif diff --git a/include/kadm5/kadm_err.h b/include/kadm5/kadm_err.h deleted file mode 100644 index 050ffca..0000000 --- a/include/kadm5/kadm_err.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * ettmp27967.h: - * This file is automatically generated; please do not edit it. - */ - -#include - -#define KADM5_FAILURE (43787520L) -#define KADM5_AUTH_GET (43787521L) -#define KADM5_AUTH_ADD (43787522L) -#define KADM5_AUTH_MODIFY (43787523L) -#define KADM5_AUTH_DELETE (43787524L) -#define KADM5_AUTH_INSUFFICIENT (43787525L) -#define KADM5_BAD_DB (43787526L) -#define KADM5_DUP (43787527L) -#define KADM5_RPC_ERROR (43787528L) -#define KADM5_NO_SRV (43787529L) -#define KADM5_BAD_HIST_KEY (43787530L) -#define KADM5_NOT_INIT (43787531L) -#define KADM5_UNK_PRINC (43787532L) -#define KADM5_UNK_POLICY (43787533L) -#define KADM5_BAD_MASK (43787534L) -#define KADM5_BAD_CLASS (43787535L) -#define KADM5_BAD_LENGTH (43787536L) -#define KADM5_BAD_POLICY (43787537L) -#define KADM5_BAD_PRINCIPAL (43787538L) -#define KADM5_BAD_AUX_ATTR (43787539L) -#define KADM5_BAD_HISTORY (43787540L) -#define KADM5_BAD_MIN_PASS_LIFE (43787541L) -#define KADM5_PASS_Q_TOOSHORT (43787542L) -#define KADM5_PASS_Q_CLASS (43787543L) -#define KADM5_PASS_Q_DICT (43787544L) -#define KADM5_PASS_REUSE (43787545L) -#define KADM5_PASS_TOOSOON (43787546L) -#define KADM5_POLICY_REF (43787547L) -#define KADM5_INIT (43787548L) -#define KADM5_BAD_PASSWORD (43787549L) -#define KADM5_PROTECT_PRINCIPAL (43787550L) -#define KADM5_BAD_SERVER_HANDLE (43787551L) -#define KADM5_BAD_STRUCT_VERSION (43787552L) -#define KADM5_OLD_STRUCT_VERSION (43787553L) -#define KADM5_NEW_STRUCT_VERSION (43787554L) -#define KADM5_BAD_API_VERSION (43787555L) -#define KADM5_OLD_LIB_API_VERSION (43787556L) -#define KADM5_OLD_SERVER_API_VERSION (43787557L) -#define KADM5_NEW_LIB_API_VERSION (43787558L) -#define KADM5_NEW_SERVER_API_VERSION (43787559L) -#define KADM5_SECURE_PRINC_MISSING (43787560L) -#define KADM5_NO_RENAME_SALT (43787561L) -#define KADM5_BAD_CLIENT_PARAMS (43787562L) -#define KADM5_BAD_SERVER_PARAMS (43787563L) -#define KADM5_AUTH_LIST (43787564L) -#define KADM5_AUTH_CHANGEPW (43787565L) -#define KADM5_GSS_ERROR (43787566L) -#define KADM5_BAD_TL_TYPE (43787567L) -#define KADM5_MISSING_CONF_PARAMS (43787568L) -#define KADM5_BAD_SERVER_NAME (43787569L) -#define KADM5_AUTH_SETKEY (43787570L) -#define KADM5_SETKEY_DUP_ENCTYPES (43787571L) -#define KADM5_SETV4KEY_INVAL_ENCTYPE (43787572L) -#define KADM5_SETKEY3_ETYPE_MISMATCH (43787573L) -#define KADM5_MISSING_KRB5_CONF_PARAMS (43787574L) -#define ERROR_TABLE_BASE_ovk (43787520L) - -extern const struct error_table et_ovk_error_table; - -#if !defined(_WIN32) -/* for compatibility with older versions... */ -extern void initialize_ovk_error_table (void) /*@modifies internalState@*/; -#else -#define initialize_ovk_error_table() -#endif - -#if !defined(_WIN32) -#define init_ovk_err_tbl initialize_ovk_error_table -#define ovk_err_base ERROR_TABLE_BASE_ovk -#endif diff --git a/include/kadm5/kadm_rpc.h b/include/kadm5/kadm_rpc.h deleted file mode 100644 index 07ffb3a..0000000 --- a/include/kadm5/kadm_rpc.h +++ /dev/null @@ -1,335 +0,0 @@ -#ifndef __KADM_RPC_H__ -#define __KADM_RPC_H__ - -#include - -#include -#include - -struct cprinc_arg { - krb5_ui_4 api_version; - kadm5_principal_ent_rec rec; - long mask; - char *passwd; -}; -typedef struct cprinc_arg cprinc_arg; -bool_t xdr_cprinc_arg(); - -struct cprinc3_arg { - krb5_ui_4 api_version; - kadm5_principal_ent_rec rec; - long mask; - int n_ks_tuple; - krb5_key_salt_tuple *ks_tuple; - char *passwd; -}; -typedef struct cprinc3_arg cprinc3_arg; -bool_t xdr_cprinc3_arg(); - -struct generic_ret { - krb5_ui_4 api_version; - kadm5_ret_t code; -}; -typedef struct generic_ret generic_ret; -bool_t xdr_generic_ret(); - -struct dprinc_arg { - krb5_ui_4 api_version; - krb5_principal princ; -}; -typedef struct dprinc_arg dprinc_arg; -bool_t xdr_dprinc_arg(); - -struct mprinc_arg { - krb5_ui_4 api_version; - kadm5_principal_ent_rec rec; - long mask; -}; -typedef struct mprinc_arg mprinc_arg; -bool_t xdr_mprinc_arg(); - -struct rprinc_arg { - krb5_ui_4 api_version; - krb5_principal src; - krb5_principal dest; -}; -typedef struct rprinc_arg rprinc_arg; -bool_t xdr_rprinc_arg(); - -struct gprincs_arg { - krb5_ui_4 api_version; - char *exp; -}; -typedef struct gprincs_arg gprincs_arg; -bool_t xdr_gprincs_arg(); - -struct gprincs_ret { - krb5_ui_4 api_version; - kadm5_ret_t code; - char **princs; - int count; -}; -typedef struct gprincs_ret gprincs_ret; -bool_t xdr_gprincs_ret(); - -struct chpass_arg { - krb5_ui_4 api_version; - krb5_principal princ; - char *pass; -}; -typedef struct chpass_arg chpass_arg; -bool_t xdr_chpass_arg(); - -struct chpass3_arg { - krb5_ui_4 api_version; - krb5_principal princ; - krb5_boolean keepold; - int n_ks_tuple; - krb5_key_salt_tuple *ks_tuple; - char *pass; -}; -typedef struct chpass3_arg chpass3_arg; -bool_t xdr_chpass3_arg(); - -struct setv4key_arg { - krb5_ui_4 api_version; - krb5_principal princ; - krb5_keyblock *keyblock; -}; -typedef struct setv4key_arg setv4key_arg; -bool_t xdr_setv4key_arg(); - -struct setkey_arg { - krb5_ui_4 api_version; - krb5_principal princ; - krb5_keyblock *keyblocks; - int n_keys; -}; -typedef struct setkey_arg setkey_arg; -bool_t xdr_setkey_arg(); - -struct setkey3_arg { - krb5_ui_4 api_version; - krb5_principal princ; - krb5_boolean keepold; - int n_ks_tuple; - krb5_key_salt_tuple *ks_tuple; - krb5_keyblock *keyblocks; - int n_keys; -}; -typedef struct setkey3_arg setkey3_arg; -bool_t xdr_setkey3_arg(); - -struct chrand_arg { - krb5_ui_4 api_version; - krb5_principal princ; -}; -typedef struct chrand_arg chrand_arg; -bool_t xdr_chrand_arg(); - -struct chrand3_arg { - krb5_ui_4 api_version; - krb5_principal princ; - krb5_boolean keepold; - int n_ks_tuple; - krb5_key_salt_tuple *ks_tuple; -}; -typedef struct chrand3_arg chrand3_arg; -bool_t xdr_chrand3_arg(); - -struct chrand_ret { - krb5_ui_4 api_version; - kadm5_ret_t code; - krb5_keyblock key; - krb5_keyblock *keys; - int n_keys; -}; -typedef struct chrand_ret chrand_ret; -bool_t xdr_chrand_ret(); - -struct gprinc_arg { - krb5_ui_4 api_version; - krb5_principal princ; - long mask; -}; -typedef struct gprinc_arg gprinc_arg; -bool_t xdr_gprinc_arg(); - -struct gprinc_ret { - krb5_ui_4 api_version; - kadm5_ret_t code; - kadm5_principal_ent_rec rec; -}; -typedef struct gprinc_ret gprinc_ret; -bool_t xdr_gprinc_ret(); -bool_t xdr_kadm5_ret_t(); -bool_t xdr_kadm5_principal_ent_rec(); -bool_t xdr_kadm5_policy_ent_rec(); -bool_t xdr_krb5_keyblock(); -bool_t xdr_krb5_principal(); -bool_t xdr_krb5_enctype(); -bool_t xdr_krb5_octet(); -bool_t xdr_krb5_int32(); -bool_t xdr_u_int32(); - -struct cpol_arg { - krb5_ui_4 api_version; - kadm5_policy_ent_rec rec; - long mask; -}; -typedef struct cpol_arg cpol_arg; -bool_t xdr_cpol_arg(); - -struct dpol_arg { - krb5_ui_4 api_version; - char *name; -}; -typedef struct dpol_arg dpol_arg; -bool_t xdr_dpol_arg(); - -struct mpol_arg { - krb5_ui_4 api_version; - kadm5_policy_ent_rec rec; - long mask; -}; -typedef struct mpol_arg mpol_arg; -bool_t xdr_mpol_arg(); - -struct gpol_arg { - krb5_ui_4 api_version; - char *name; -}; -typedef struct gpol_arg gpol_arg; -bool_t xdr_gpol_arg(); - -struct gpol_ret { - krb5_ui_4 api_version; - kadm5_ret_t code; - kadm5_policy_ent_rec rec; -}; -typedef struct gpol_ret gpol_ret; -bool_t xdr_gpol_ret(); - -struct gpols_arg { - krb5_ui_4 api_version; - char *exp; -}; -typedef struct gpols_arg gpols_arg; -bool_t xdr_gpols_arg(); - -struct gpols_ret { - krb5_ui_4 api_version; - kadm5_ret_t code; - char **pols; - int count; -}; -typedef struct gpols_ret gpols_ret; -bool_t xdr_gpols_ret(); - -struct getprivs_ret { - krb5_ui_4 api_version; - kadm5_ret_t code; - long privs; -}; -typedef struct getprivs_ret getprivs_ret; -bool_t xdr_getprivs_ret(); - -#define KADM ((krb5_ui_4)2112) -#define KADMVERS ((krb5_ui_4)2) -#define CREATE_PRINCIPAL ((krb5_ui_4)1) -extern generic_ret *create_principal_1_svc(cprinc_arg *arg, - struct svc_req *rqstp); -extern generic_ret *create_principal_1(cprinc_arg *argp, CLIENT *clnt); - -#define DELETE_PRINCIPAL ((krb5_ui_4)2) -extern generic_ret *delete_principal_1_svc(dprinc_arg *arg, - struct svc_req *rqstp); -extern generic_ret *delete_principal_1(dprinc_arg *argp, CLIENT *clnt); - -#define MODIFY_PRINCIPAL ((krb5_ui_4)3) -extern generic_ret *modify_principal_1_svc(mprinc_arg *arg, - struct svc_req *rqstp); -extern generic_ret *modify_principal_1(mprinc_arg *argp, CLIENT *clnt); - -#define RENAME_PRINCIPAL ((krb5_ui_4)4) -extern generic_ret *rename_principal_1_svc(rprinc_arg *arg, - struct svc_req *rqstp); -extern generic_ret *rename_principal_1(rprinc_arg *argp, CLIENT *clnt); - -#define GET_PRINCIPAL ((krb5_ui_4)5) -extern gprinc_ret *get_principal_1_svc(gprinc_arg *arg, struct svc_req *rqstp); -extern gprinc_ret *get_principal_1(gprinc_arg *argp, CLIENT *clnt); - -#define CHPASS_PRINCIPAL ((krb5_ui_4)6) -extern generic_ret *chpass_principal_1_svc(chpass_arg *arg, - struct svc_req *rqstp); -extern generic_ret *chpass_principal_1(chpass_arg *argp, CLIENT *clnt); - -#define CHRAND_PRINCIPAL ((krb5_ui_4)7) -extern chrand_ret *chrand_principal_1_svc(chrand_arg *arg, - struct svc_req *rqstp); -extern chrand_ret *chrand_principal_1(chrand_arg *argp, CLIENT *clnt); - -#define CREATE_POLICY ((krb5_ui_4)8) -extern generic_ret *create_policy_1_svc(cpol_arg *arg, struct svc_req *rqstp); -extern generic_ret *create_policy_1(cpol_arg *argp, CLIENT *clnt); - -#define DELETE_POLICY ((krb5_ui_4)9) -extern generic_ret *delete_policy_1_svc(dpol_arg *arg, struct svc_req *rqstp); -extern generic_ret *delete_policy_1(dpol_arg *argp, CLIENT *clnt); - -#define MODIFY_POLICY ((krb5_ui_4)10) -extern generic_ret *modify_policy_1_svc(mpol_arg *arg, struct svc_req *rqstp); -extern generic_ret *modify_policy_1(mpol_arg *argp, CLIENT *clnt); - -#define GET_POLICY ((krb5_ui_4)11) -extern gpol_ret *get_policy_1_svc(gpol_arg *arg, struct svc_req *rqstp); -extern gpol_ret *get_policy_1(gpol_arg *argp, CLIENT *clnt); - -#define GET_PRIVS ((krb5_ui_4)12) -extern getprivs_ret *get_privs_1_svc(krb5_ui_4 *arg, struct svc_req *rqstp); -extern getprivs_ret *get_privs_1(void *argp, CLIENT *clnt); - -#define INIT ((krb5_ui_4)13) -extern generic_ret *init_1_svc(krb5_ui_4 *arg, struct svc_req *rqstp); -extern generic_ret *init_1(void *argp, CLIENT *clnt); - -#define GET_PRINCS ((krb5_ui_4) 14) -extern gprincs_ret *get_princs_1_svc(gprincs_arg *arg, struct svc_req *rqstp); -extern gprincs_ret *get_princs_1(gprincs_arg *argp, CLIENT *clnt); - -#define GET_POLS ((krb5_ui_4) 15) -extern gpols_ret *get_pols_1_svc(gpols_arg *arg, struct svc_req *rqstp); -extern gpols_ret *get_pols_1(gpols_arg *argp, CLIENT *clnt); - -#define SETKEY_PRINCIPAL ((krb5_ui_4) 16) -extern generic_ret *setkey_principal_1_svc(setkey_arg *arg, - struct svc_req *rqstp); -extern generic_ret *setkey_principal_1(setkey_arg *argp, CLIENT *clnt); - -#define SETV4KEY_PRINCIPAL ((krb5_ui_4) 17) -extern generic_ret *setv4key_principal_1_svc(setv4key_arg *arg, - struct svc_req *rqstp); -extern generic_ret *setv4key_principal_1(setv4key_arg *argp, CLIENT *clnt); - -#define CREATE_PRINCIPAL3 ((krb5_ui_4) 18) -extern generic_ret *create_principal3_1_svc(cprinc3_arg *arg, - struct svc_req *rqstp); -extern generic_ret *create_principal3_1(cprinc3_arg *argp, CLIENT *clnt); - -#define CHPASS_PRINCIPAL3 ((krb5_ui_4) 19) -extern generic_ret *chpass_principal3_1_svc(chpass3_arg *arg, - struct svc_req *rqstp); -extern generic_ret *chpass_principal3_1(chpass3_arg *argp, CLIENT *clnt); - -#define CHRAND_PRINCIPAL3 ((krb5_ui_4) 20) -extern chrand_ret *chrand_principal3_1_svc(chrand3_arg *arg, - struct svc_req *rqstp); -extern chrand_ret *chrand_principal3_1(chrand3_arg *argp, CLIENT *clnt); - -#define SETKEY_PRINCIPAL3 ((krb5_ui_4) 21) -extern generic_ret *setkey_principal3_1_svc(setkey3_arg *arg, - struct svc_req *rqstp); -extern generic_ret *setkey_principal3_1(setkey3_arg *argp, CLIENT *clnt); - -#endif /* __KADM_RPC_H__ */ diff --git a/include/kdb.h b/include/kdb.h deleted file mode 100644 index e704908..0000000 --- a/include/kdb.h +++ /dev/null @@ -1,334 +0,0 @@ -/* - * include/krb5/kdb.h - * - * Copyright 1990,1991 by the Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * - * KDC Database interface definitions. - */ - -/* - * Copyright (C) 1998 by the FundsXpress, INC. - * - * All rights reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of FundsXpress. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. FundsXpress makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef KRB5_KDB5__ -#define KRB5_KDB5__ - -/* Salt types */ -#define KRB5_KDB_SALTTYPE_NORMAL 0 -#define KRB5_KDB_SALTTYPE_V4 1 -#define KRB5_KDB_SALTTYPE_NOREALM 2 -#define KRB5_KDB_SALTTYPE_ONLYREALM 3 -#define KRB5_KDB_SALTTYPE_SPECIAL 4 -#define KRB5_KDB_SALTTYPE_AFS3 5 - -/* Attributes */ -#define KRB5_KDB_DISALLOW_POSTDATED 0x00000001 -#define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002 -#define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004 -#define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008 -#define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010 -#define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020 -#define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040 -#define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080 -#define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100 -#define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200 -#define KRB5_KDB_DISALLOW_SVR 0x00001000 -#define KRB5_KDB_PWCHANGE_SERVICE 0x00002000 -#define KRB5_KDB_SUPPORT_DESMD5 0x00004000 -#define KRB5_KDB_NEW_PRINC 0x00008000 - -/* Creation flags */ -#define KRB5_KDB_CREATE_BTREE 0x00000001 -#define KRB5_KDB_CREATE_HASH 0x00000002 - -#if !defined(_WIN32) - -/* - * Note --- these structures cannot be modified without changing the - * database version number in libkdb.a, but should be expandable by - * adding new tl_data types. - */ -typedef struct _krb5_tl_data { - struct _krb5_tl_data* tl_data_next; /* NOT saved */ - krb5_int16 tl_data_type; - krb5_ui_2 tl_data_length; - krb5_octet * tl_data_contents; -} krb5_tl_data; - -/* - * If this ever changes up the version number and make the arrays be as - * big as necessary. - * - * Currently the first type is the enctype and the second is the salt type. - */ -typedef struct _krb5_key_data { - krb5_int16 key_data_ver; /* Version */ - krb5_int16 key_data_kvno; /* Key Version */ - krb5_int16 key_data_type[2]; /* Array of types */ - krb5_ui_2 key_data_length[2]; /* Array of lengths */ - krb5_octet * key_data_contents[2]; /* Array of pointers */ -} krb5_key_data; - -#define KRB5_KDB_V1_KEY_DATA_ARRAY 2 /* # of array elements */ - -typedef struct _krb5_keysalt { - krb5_int16 type; - krb5_data data; /* Length, data */ -} krb5_keysalt; - -typedef struct _krb5_db_entry_new { - krb5_magic magic; /* NOT saved */ - krb5_ui_2 len; - krb5_flags attributes; - krb5_deltat max_life; - krb5_deltat max_renewable_life; - krb5_timestamp expiration; /* When the client expires */ - krb5_timestamp pw_expiration; /* When its passwd expires */ - krb5_timestamp last_success; /* Last successful passwd */ - krb5_timestamp last_failed; /* Last failed passwd attempt */ - krb5_kvno fail_auth_count; /* # of failed passwd attempt */ - krb5_int16 n_tl_data; - krb5_int16 n_key_data; - krb5_ui_2 e_length; /* Length of extra data */ - krb5_octet * e_data; /* Extra data to be saved */ - - krb5_principal princ; /* Length, data */ - krb5_tl_data * tl_data; /* Linked list */ - krb5_key_data * key_data; /* Array */ -} krb5_db_entry; - -#define KRB5_KDB_MAGIC_NUMBER 0xdbdbdbdb -#define KRB5_KDB_V1_BASE_LENGTH 38 - -#define KRB5_TL_LAST_PWD_CHANGE 0x0001 -#define KRB5_TL_MOD_PRINC 0x0002 -#define KRB5_TL_KADM_DATA 0x0003 -#define KRB5_TL_KADM5_E_DATA 0x0004 -#define KRB5_TL_RB1_CHALLENGE 0x0005 -#ifdef SECURID -#define KRB5_TL_SECURID_STATE 0x0006 -#endif /* SECURID */ - -/* - * Determines the number of failed KDC requests before DISALLOW_ALL_TIX is set - * on the principal. - */ -#define KRB5_MAX_FAIL_COUNT 5 - -/* XXX depends on knowledge of krb5_parse_name() formats */ -#define KRB5_KDB_M_NAME "K/M" /* Kerberos/Master */ - -/* prompts used by default when reading the KDC password from the keyboard. */ -#define KRB5_KDC_MKEY_1 "Enter KDC database master key" -#define KRB5_KDC_MKEY_2 "Re-enter KDC database master key to verify" - -extern char *krb5_mkey_pwd_prompt1; -extern char *krb5_mkey_pwd_prompt2; - -/* - * These macros specify the encoding of data within the database. - * - * Data encoding is little-endian. - */ -#define krb5_kdb_decode_int16(cp, i16) \ - *((krb5_int16 *) &(i16)) = (((krb5_int16) ((unsigned char) (cp)[0]))| \ - ((krb5_int16) ((unsigned char) (cp)[1]) << 8)) -#define krb5_kdb_decode_int32(cp, i32) \ - *((krb5_int32 *) &(i32)) = (((krb5_int32) ((unsigned char) (cp)[0]))| \ - ((krb5_int32) ((unsigned char) (cp)[1]) << 8) | \ - ((krb5_int32) ((unsigned char) (cp)[2]) << 16)| \ - ((krb5_int32) ((unsigned char) (cp)[3]) << 24)) -#define krb5_kdb_encode_int16(i16, cp) \ - { \ - (cp)[0] = (unsigned char) ((i16) & 0xff); \ - (cp)[1] = (unsigned char) (((i16) >> 8) & 0xff); \ - } -#define krb5_kdb_encode_int32(i32, cp) \ - { \ - (cp)[0] = (unsigned char) ((i32) & 0xff); \ - (cp)[1] = (unsigned char) (((i32) >> 8) & 0xff); \ - (cp)[2] = (unsigned char) (((i32) >> 16) & 0xff); \ - (cp)[3] = (unsigned char) (((i32) >> 24) & 0xff); \ - } - -/* libkdb.spec */ -krb5_error_code krb5_db_set_name (krb5_context, char * ); -krb5_error_code krb5_db_init (krb5_context); -krb5_error_code krb5_db_fini (krb5_context); -krb5_error_code krb5_db_get_age (krb5_context, char *, time_t * ); -krb5_error_code krb5_db_create (krb5_context, char *, krb5_int32 ); -krb5_error_code krb5_db_rename (krb5_context, char *, char * ); -krb5_error_code krb5_db_get_principal (krb5_context, krb5_const_principal , - krb5_db_entry *, int *, - krb5_boolean * ); -void krb5_db_free_principal (krb5_context, krb5_db_entry *, int ); -krb5_error_code krb5_db_put_principal (krb5_context, krb5_db_entry *, int * ); -krb5_error_code krb5_db_delete_principal (krb5_context, krb5_const_principal, - int * ); -krb5_error_code krb5_db_iterate (krb5_context, - krb5_error_code (* ) (krb5_pointer, - krb5_db_entry *), - krb5_pointer); -krb5_error_code krb5_db_iterate_ext (krb5_context, - krb5_error_code (* ) (krb5_pointer, - krb5_db_entry *), - krb5_pointer, int, int); -krb5_error_code krb5_db_verify_master_key (krb5_context, krb5_principal, - krb5_keyblock *); -krb5_error_code krb5_db_store_mkey (krb5_context, char *, krb5_principal, - krb5_keyblock *); - -krb5_error_code krb5_db_setup_mkey_name (krb5_context, const char *, - const char *, char **, - krb5_principal *); - -krb5_error_code krb5_db_set_mkey (krb5_context, krb5_keyblock *); - -krb5_error_code krb5_db_get_mkey (krb5_context, krb5_keyblock **); -krb5_error_code krb5_db_destroy (krb5_context, char * ); -krb5_error_code krb5_db_lock (krb5_context, int ); -krb5_error_code krb5_db_unlock (krb5_context); -krb5_error_code krb5_db_set_nonblocking (krb5_context, krb5_boolean, - krb5_boolean * ); -krb5_boolean krb5_db_set_lockmode (krb5_context, krb5_boolean); -krb5_error_code krb5_db_fetch_mkey (krb5_context, krb5_principal, krb5_enctype, - krb5_boolean, krb5_boolean, char *, - krb5_data *, - krb5_keyblock * ); - -krb5_error_code krb5_db_open_database (krb5_context); -krb5_error_code krb5_db_close_database (krb5_context); - -krb5_error_code krb5_dbekd_encrypt_key_data (krb5_context, - const krb5_keyblock *, - const krb5_keyblock *, - const krb5_keysalt *, - int, - krb5_key_data *); -krb5_error_code krb5_dbekd_decrypt_key_data (krb5_context, - const krb5_keyblock *, - const krb5_key_data *, - krb5_keyblock *, - krb5_keysalt *); -krb5_error_code krb5_dbe_create_key_data (krb5_context, - krb5_db_entry *); -krb5_error_code krb5_dbe_update_tl_data (krb5_context, - krb5_db_entry *, - krb5_tl_data *); -krb5_error_code krb5_dbe_lookup_tl_data (krb5_context, - krb5_db_entry *, - krb5_tl_data *); -krb5_error_code krb5_dbe_update_last_pwd_change (krb5_context, - krb5_db_entry *, - krb5_timestamp); -krb5_error_code krb5_dbe_lookup_last_pwd_change (krb5_context, - krb5_db_entry *, - krb5_timestamp *); -krb5_error_code krb5_dbe_update_mod_princ_data (krb5_context, - krb5_db_entry *, - krb5_timestamp, - krb5_const_principal); -krb5_error_code krb5_dbe_lookup_mod_princ_data (krb5_context, - krb5_db_entry *, - krb5_timestamp *, - krb5_principal *); -int krb5_encode_princ_dbkey (krb5_context, krb5_data *, krb5_const_principal); -void krb5_free_princ_dbkey (krb5_context, krb5_data *); -krb5_error_code krb5_encode_princ_contents (krb5_context, krb5_data *, - krb5_db_entry *); -void krb5_free_princ_contents (krb5_context, krb5_data *); -krb5_error_code krb5_decode_princ_contents (krb5_context, krb5_data *, - krb5_db_entry *); -void krb5_dbe_free_contents (krb5_context, krb5_db_entry *); - -krb5_error_code krb5_dbe_find_enctype (krb5_context, krb5_db_entry *, - krb5_int32, - krb5_int32, - krb5_int32, - krb5_key_data **); - -krb5_error_code krb5_dbe_search_enctype (krb5_context, - krb5_db_entry *, - krb5_int32 *, - krb5_int32, - krb5_int32, - krb5_int32, - krb5_key_data **); - -struct __krb5_key_salt_tuple; - -krb5_error_code krb5_dbe_cpw (krb5_context, - krb5_keyblock *, - struct __krb5_key_salt_tuple *, - int, - char *, - int, - krb5_boolean, - krb5_db_entry *); -krb5_error_code krb5_dbe_apw (krb5_context, - krb5_keyblock *, - struct __krb5_key_salt_tuple *, - int, - char *, - krb5_db_entry *); -krb5_error_code krb5_dbe_crk (krb5_context, - krb5_keyblock *, - struct __krb5_key_salt_tuple *, - int, - krb5_boolean, - krb5_db_entry *); -krb5_error_code krb5_dbe_ark (krb5_context, - krb5_keyblock *, - struct __krb5_key_salt_tuple *, - int, - krb5_db_entry *); - -krb5_error_code krb5_ser_db_context_init (krb5_context); - -#define KRB5_KDB_DEF_FLAGS 0 - -#endif /* !defined(_WIN32) */ -#endif /* KRB5_KDB5__ */ diff --git a/src/Makefile b/src/Makefile index 5dff35f..5fa0187 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ CFLAGS := -g3 -O2 -Wall -Werror -DDEBUG LDFLAGS := -L/opt/csw/lib -Wl,-R/opt/csw/lib -L/usr/local/lib -Wl,-R/usr/local/lib -INCLUDES := -I../include $(shell krb5-config --cflags) +INCLUDES := $(shell krb5-config --cflags) override LDFLAGS += -std=gnu99 $(INCLUDES) override CFLAGS += -std=gnu99 $(INCLUDES) From 47b601d2242457638a6dce22b0f09d8a6299997a Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 25 Jul 2009 05:53:54 -0400 Subject: [PATCH 25/40] Update call to kadm5_init_with_skey --- src/kadm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/kadm.c b/src/kadm.c index e2a1669..5075d52 100644 --- a/src/kadm.c +++ b/src/kadm.c @@ -16,10 +16,10 @@ void ceo_kadm_init() { debug("kadmin: initializing using keytab for %s", admin_principal); - retval = kadm5_init_with_skey(admin_principal, NULL /*admin_keytab */, + retval = kadm5_init_with_skey(admin_principal, NULL, KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, - KADM5_API_VERSION_2, &handle); - if (retval) { + KADM5_API_VERSION_2, NULL, &handle); + if (retval || !handle) { com_err(prog, retval, "while initializing kadm5"); exit(1); } From 49bdd24661dd4c8bf7cf31b8b7777d7191377499 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 07:28:53 -0400 Subject: [PATCH 26/40] Remove Solaris LDFLAGS --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 5fa0187..c086fb7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,4 @@ CFLAGS := -g3 -O2 -Wall -Werror -DDEBUG -LDFLAGS := -L/opt/csw/lib -Wl,-R/opt/csw/lib -L/usr/local/lib -Wl,-R/usr/local/lib INCLUDES := $(shell krb5-config --cflags) override LDFLAGS += -std=gnu99 $(INCLUDES) override CFLAGS += -std=gnu99 $(INCLUDES) From a838e28a2cd805a7016d31da9033955b2b09bc2c Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 07:29:31 -0400 Subject: [PATCH 27/40] Ignore debhelper log --- debian/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/.gitignore b/debian/.gitignore index c5d55af..5e861a7 100644 --- a/debian/.gitignore +++ b/debian/.gitignore @@ -2,3 +2,4 @@ /ceo /files /*.debhelper +/*.debhelper.log From 99ce020ba0dd4cc65d5f5501f3cbac7144efecac Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 07:30:58 -0400 Subject: [PATCH 28/40] Fix changelog version --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index e545cc2..503eb9c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ -ceo (0.4.10) stable testing; urgency=low +ceo (0.4.19) stable testing; urgency=low * Bump standards version. - -- Michael Spang Fri, 24 Jul 2009 18:47:33 -0400 + -- Michael Spang Wed, 29 Jul 2009 07:31:24 -0400 ceo (0.4.18) stable testing; urgency=low From 6b83cc5c05e24cbac1bfbba4edbeff40f6317fdc Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 08:18:35 -0400 Subject: [PATCH 29/40] Abort on unexpected SCTP errors --- src/net.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/net.c b/src/net.c index 5bf3be7..dc85682 100644 --- a/src/net.c +++ b/src/net.c @@ -71,6 +71,19 @@ static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strb case SCTP_SHUTDOWN_EVENT: fatal("connection shut down"); break; + case SCTP_ASSOC_CHANGE: + switch (sn->sn_assoc_change.sac_state) { + case SCTP_COMM_LOST: + fatal("connection lost"); + break; + case SCTP_SHUTDOWN_COMP: + fatal("shutdown complete"); + break; + case SCTP_CANT_STR_ASSOC: + fatal("cannot start association"); + break; + } + break; } } From 0d52c0475b84fbab40f24628cef1612c7920360c Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 08:30:08 -0400 Subject: [PATCH 30/40] Kill zfsaddhomedir --- src/Makefile | 6 +- src/zfsaddhomedir.c | 139 -------------------------------------------- 2 files changed, 3 insertions(+), 142 deletions(-) delete mode 100644 src/zfsaddhomedir.c diff --git a/src/Makefile b/src/Makefile index c086fb7..e9ac610 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ override CFLAGS += -std=gnu99 $(INCLUDES) DESTDIR := PREFIX := /usr/local -BIN_PROGS := addmember addclub zfsaddhomedir ceod +BIN_PROGS := addmember addclub ceod LIB_PROGS := ceoc op-adduser EXT_PROGS := config-test @@ -26,7 +26,7 @@ CONFIG_OBJECTS := config.o parser.o CONFIG_LDFLAGS := CONFIG_PROGS := $(LDAP_PROGS) $(KRB5_PROGS) $(NET_PROGS) UTIL_OBJECTS := util.o strbuf.o -UTIL_PROGS := config-test zfsaddhomedir $(CONFIG_PROGS) +UTIL_PROGS := config-test $(CONFIG_PROGS) all: $(BIN_PROGS) $(LIB_PROGS) $(EXT_PROGS) @@ -65,4 +65,4 @@ $(UTIL_PROGS): LDFLAGS += $(UTIL_LDFLAGS) $(UTIL_PROGS): $(UTIL_OBJECTS) .PHONY: clean all -.SECONDARY: ceoc.o zfsaddhomedir.o addmember.o addclub.o +.SECONDARY: ceoc.o addmember.o addclub.o diff --git a/src/zfsaddhomedir.c b/src/zfsaddhomedir.c deleted file mode 100644 index ae556f6..0000000 --- a/src/zfsaddhomedir.c +++ /dev/null @@ -1,139 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "util.h" - -int main(int argc, char *argv[]) { - if(argc < 7) { - fprintf(stderr, "Usage: zfsaddhomedir homedir refquota skeldir uid gid mode acl\n"); - return 1; - } - - char *homedir = argv[1]; - char *skeldir = argv[3]; - char refquota[32]; - char *mode = argv[6]; - char *acl = (argc >= 8) ? argv[7] : NULL; - uid_t uid, gid; - char *zfs_bin = "/usr/sbin/zfs"; - char *chmod_bin = "/usr/bin/chmod"; - char *dataset = homedir + 1; - char *create_argv[] = { "zfs", "create", dataset, NULL }; - char *quota_argv[] = { "zfs", "set", refquota, dataset, NULL }; - char *mode_argv[] = { "chmod", mode, homedir, NULL }; - char *acl_argv[] = { "chmod", acl, homedir, NULL }; - DIR *skel; - struct dirent *skelent; - - assert(homedir[0]); - uid = atol(argv[4]); - gid = atol(argv[5]); - snprintf(refquota, sizeof(refquota), "refquota=%s", argv[2]); - - if(spawnv(zfs_bin, create_argv)) - return 1; - if(spawnv(zfs_bin, quota_argv)) - return 1; - if(spawnv(chmod_bin, mode_argv)) - return 1; - if(acl && spawnv(chmod_bin, acl_argv)) - return 1; - - skel = opendir(skeldir); - if (!skel) { - errorpe("failed to open %s", skeldir); - return -1; - } - - while ((skelent = readdir(skel))) { - struct stat sb; - char src[PATH_MAX], dest[PATH_MAX]; - - if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, "..")) - continue; - - snprintf(src, sizeof(src), "%s/%s", skeldir, skelent->d_name); - snprintf(dest, sizeof(dest), "/%s/%s", homedir, skelent->d_name); - lstat(src, &sb); - - if (sb.st_uid || sb.st_gid) { - warn("not creating %s due to ownership", dest); - continue; - } - - if (S_ISREG(sb.st_mode)) { - int bytes; - char buf[4096]; - - int srcfd = open(src, O_RDONLY); - if (srcfd == -1) { - warnpe("open: %s", src); - continue; - } - - int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, sb.st_mode & 0777); - if (destfd == -1) { - warnpe("open: %s", dest); - close(srcfd); - continue; - } - - for (;;) { - bytes = read(srcfd, buf, sizeof(buf)); - if (!bytes) - break; - if (bytes < 0) { - warnpe("read"); - break; - } - if (write(destfd, buf, bytes) < 0) { - warnpe("write"); - break; - } - } - if (fchown(destfd, uid, gid)) - errorpe("chown: %s", dest); - - close(srcfd); - close(destfd); - } else if (S_ISDIR(sb.st_mode)) { - if (mkdir(dest, sb.st_mode & 0777)) { - warnpe("mkdir: %s", dest); - continue; - } - if (chown(dest, uid, gid)) - errorpe("chown: %s", dest); - } else if (S_ISLNK(sb.st_mode)) { - char lnkdest[PATH_MAX]; - int bytes; - bytes = readlink(src, lnkdest, sizeof(lnkdest)); - lnkdest[bytes] = '\0'; - if (bytes == -1) { - warnpe("readlink: %s", src); - continue; - } - if (symlink(lnkdest, dest)) { - warnpe("symlink: %s", dest); - continue; - } - if (lchown(dest, uid, gid)) - errorpe("lchown: %s", dest); - } else { - warn("not creating %s", dest); - } - } - - closedir(skel); - - if (chown(homedir, uid, gid)) { - errorpe("failed to chown %s", homedir); - return -1; - } - - return 0; -} From 37eb3e6465604294894cc0f4698174ca906a6f1a Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 08:56:20 -0400 Subject: [PATCH 31/40] Resurrect linux homedir support --- debian/control | 2 +- src/Makefile | 5 ++ src/config-vars.h | 4 -- src/homedir.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++ src/homedir.h | 3 ++ src/op-adduser.c | 15 ++++-- 6 files changed, 141 insertions(+), 9 deletions(-) create mode 100644 src/homedir.c create mode 100644 src/homedir.h diff --git a/debian/control b/debian/control index 80500d3..46595da 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: ceo Section: admin Priority: optional Maintainer: Systems Committee -Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev, libsctp-dev, libprotobuf-c0-dev +Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev, libsctp-dev, libprotobuf-c0-dev, libacl1-dev Standards-Version: 3.8.2 Package: ceo diff --git a/src/Makefile b/src/Makefile index e9ac610..7b4bec0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,6 +16,9 @@ LDAP_PROGS := addmember addclub op-adduser KRB5_OBJECTS := krb5.o kadm.o KRB5_LDFLAGS := $(shell krb5-config --libs krb5 kadm-client) KRB5_PROGS := addmember addclub op-adduser +HOME_OBJECTS := homedir.o +HOME_LDFLAGS := -lacl +HOME_PROGS := op-adduser NET_OBJECTS := net.o gss.o ops.o NET_LDFLAGS := -lsctp $(shell krb5-config --libs gssapi) NET_PROGS := ceod ceoc @@ -57,6 +60,8 @@ $(LDAP_PROGS): LDFLAGS += $(LDAP_LDFLAGS) $(LDAP_PROGS): $(LDAP_OBJECTS) $(KRB5_PROGS): LDFLAGS += $(KRB5_LDFLAGS) $(KRB5_PROGS): $(KRB5_OBJECTS) +$(HOME_PROGS): LDFLAGS += $(HOME_LDFLAGS) +$(HOME_PROGS): $(HOME_OBJECTS) $(PROTO_PROGS): LDFLAGS += $(PROTO_LDFLAGS) $(PROTO_PROGS): $(PROTO_OBJECTS) $(CONFIG_PROGS): LDFLAGS += $(CONFIG_LDFLAGS) diff --git a/src/config-vars.h b/src/config-vars.h index 2c2334c..c7a2094 100644 --- a/src/config-vars.h +++ b/src/config-vars.h @@ -5,20 +5,16 @@ CONFIG_STR(groups_base) CONFIG_STR(sudo_base) CONFIG_STR(skeleton_dir) -CONFIG_STR(homedir_mode) -CONFIG_STR(refquota) CONFIG_STR(member_shell) CONFIG_INT(member_min_id) CONFIG_INT(member_max_id) CONFIG_STR(member_home) -CONFIG_STR(member_home_acl) CONFIG_STR(club_shell) CONFIG_INT(club_min_id) CONFIG_INT(club_max_id) CONFIG_STR(club_home) -CONFIG_STR(club_home_acl) CONFIG_STR(notify_hook) diff --git a/src/homedir.c b/src/homedir.c new file mode 100644 index 0000000..83772df --- /dev/null +++ b/src/homedir.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "homedir.h" +#include "util.h" +#include "config.h" + +int ceo_create_home(char *homedir, uid_t uid, gid_t gid) { + int mask; + DIR *skel; + struct dirent *skelent; + + mask = umask(0); + + if (mkdir(homedir, 0755)) { + errorpe("failed to create %s", homedir); + return -1; + } + + skel = opendir(skeleton_dir); + if (!skel) { + errorpe("failed to open %s", skeleton_dir); + return -1; + } + + while ((skelent = readdir(skel))) { + struct stat sb; + char src[PATH_MAX], dest[PATH_MAX]; + + if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, "..")) + continue; + + snprintf(src, sizeof(src), "%s/%s", skeleton_dir, skelent->d_name); + snprintf(dest, sizeof(dest), "%s/%s", homedir, skelent->d_name); + lstat(src, &sb); + + if (sb.st_uid || sb.st_gid) { + warn("not creating %s due to ownership", dest); + continue; + } + + if (S_ISREG(sb.st_mode)) { + int bytes; + char buf[4096]; + + int srcfd = open(src, O_RDONLY); + if (srcfd == -1) { + warnpe("open: %s", src); + continue; + } + + int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, sb.st_mode & 0777); + if (destfd == -1) { + warnpe("open: %s", dest); + close(srcfd); + continue; + } + + for (;;) { + bytes = read(srcfd, buf, sizeof(buf)); + if (!bytes) + break; + if (bytes < 0) { + warnpe("read"); + break; + } + if (write(destfd, buf, bytes) < 0) { + warnpe("write"); + break; + } + } + + if (fchown(destfd, uid, gid)) + errorpe("chown: %s", dest); + + close(srcfd); + close(destfd); + } else if (S_ISDIR(sb.st_mode)) { + if (mkdir(dest, sb.st_mode & 0777)) { + warnpe("mkdir: %s", dest); + continue; + } + if (chown(dest, uid, gid)) + errorpe("chown: %s", dest); + } else if (S_ISLNK(sb.st_mode)) { + char lnkdest[PATH_MAX]; + int bytes; + bytes = readlink(src, lnkdest, sizeof(lnkdest)); + lnkdest[bytes] = '\0'; + if (bytes == -1) { + warnpe("readlink: %s", src); + continue; + } + if (symlink(lnkdest, dest)) { + warnpe("symlink: %s", dest); + continue; + } + if (lchown(dest, uid, gid)) + errorpe("lchown: %s", dest); + } else { + warn("not creating %s", dest); + } + } + + closedir(skel); + + if (chown(homedir, uid, gid)) { + errorpe("failed to chown %s", homedir); + return -1; + } + + umask(mask); + + return 0; +} diff --git a/src/homedir.h b/src/homedir.h new file mode 100644 index 0000000..8bc04bf --- /dev/null +++ b/src/homedir.h @@ -0,0 +1,3 @@ +#include + +int ceo_create_home(char *homedir, uid_t uid, gid_t gid); diff --git a/src/op-adduser.c b/src/op-adduser.c index c75f8bb..17f3602 100644 --- a/src/op-adduser.c +++ b/src/op-adduser.c @@ -19,6 +19,7 @@ #include "gss.h" #include "krb5.h" #include "ldap.h" +#include "homedir.h" #include "kadm.h" #include "daemon.h" #include "strbuf.h" @@ -136,7 +137,7 @@ static void adduser_spam(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *clie static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) { char homedir[1024]; - int user_stat, group_stat, krb_stat; + int user_stat, group_stat, krb_stat, home_stat; int id; if (snprintf(homedir, sizeof(homedir), "%s/%s", @@ -165,12 +166,15 @@ static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) { else response_message(out, 0, "successfully created ldap group"); - return krb_stat || user_stat || group_stat; + if ((home_stat = ceo_create_home(homedir, id, id))) + notice("successfully created home directory for %s", in->username); + + return krb_stat || user_stat || group_stat || home_stat; } static int32_t addclub(Ceo__AddUser *in, Ceo__AddUserResponse *out) { char homedir[1024]; - int krb_stat, user_stat, group_stat, sudo_stat; + int krb_stat, user_stat, group_stat, sudo_stat, home_stat; int id; if (snprintf(homedir, sizeof(homedir), "%s/%s", @@ -200,7 +204,10 @@ static int32_t addclub(Ceo__AddUser *in, Ceo__AddUserResponse *out) { else response_message(out, 0, "successfully created ldap sudoers"); - return user_stat || group_stat || sudo_stat; + if ((home_stat = ceo_create_home(homedir, id, id))) + notice("successfully created home directory for %s", in->username); + + return user_stat || group_stat || sudo_stat || home_stat; } static int32_t adduser(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *client) { From e210f7d38b7da47b8ffee6b523fd39ae51a932a7 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 08:58:48 -0400 Subject: [PATCH 32/40] Remove unused vars --- ceo/members.py | 2 +- src/config-vars.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/ceo/members.py b/ceo/members.py index d78f04d..dfcd951 100644 --- a/ceo/members.py +++ b/ceo/members.py @@ -26,7 +26,7 @@ def configure(): string_fields = [ 'username_regex', 'shells_file', 'server_url', 'users_base', 'groups_base', 'sasl_mech', 'sasl_realm', 'admin_bind_keytab', 'admin_bind_userid', 'realm', - 'admin_principal', 'admin_keytab', 'expired_account_email', + 'admin_principal', 'expired_account_email', 'mathsoc_regex', 'mathsoc_dont_count' ] numeric_fields = [ 'min_password_length' ] diff --git a/src/config-vars.h b/src/config-vars.h index c7a2094..36f7a4c 100644 --- a/src/config-vars.h +++ b/src/config-vars.h @@ -22,5 +22,3 @@ CONFIG_STR(realm) CONFIG_STR(admin_principal) CONFIG_STR(admin_bind_userid) - -CONFIG_STR(privileged_group) From bfff0e8e87610a81822f29c9f90296ee2bc7ee5d Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 09:22:01 -0400 Subject: [PATCH 33/40] Use --as-needed when linking This avoids complaints by dpkg due to unnecessary links. --- debian/rules | 2 +- src/Makefile | 29 +++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/debian/rules b/debian/rules index 4a7303b..2c1caf1 100755 --- a/debian/rules +++ b/debian/rules @@ -1,7 +1,7 @@ #!/usr/bin/make -f CFLAGS := -g -O2 -fstack-protector-all -fPIE -LDFLAGS := -pie +LDFLAGS := -pie -Wl,--as-needed build: python setup.py -q build diff --git a/src/Makefile b/src/Makefile index 7b4bec0..47bbc98 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,5 @@ CFLAGS := -g3 -O2 -Wall -Werror -DDEBUG +LDFLAGS := -Wl,--as-needed INCLUDES := $(shell krb5-config --cflags) override LDFLAGS += -std=gnu99 $(INCLUDES) override CFLAGS += -std=gnu99 $(INCLUDES) @@ -11,22 +12,22 @@ LIB_PROGS := ceoc op-adduser EXT_PROGS := config-test LDAP_OBJECTS := ldap.o -LDAP_LDFLAGS := -lldap +LDAP_LIBS := -lldap LDAP_PROGS := addmember addclub op-adduser KRB5_OBJECTS := krb5.o kadm.o -KRB5_LDFLAGS := $(shell krb5-config --libs krb5 kadm-client) +KRB5_LIBS := $(shell krb5-config --libs krb5 kadm-client) KRB5_PROGS := addmember addclub op-adduser HOME_OBJECTS := homedir.o -HOME_LDFLAGS := -lacl +HOME_LIBS := -lacl HOME_PROGS := op-adduser NET_OBJECTS := net.o gss.o ops.o -NET_LDFLAGS := -lsctp $(shell krb5-config --libs gssapi) +NET_LIBS := -lsctp $(shell krb5-config --libs gssapi) NET_PROGS := ceod ceoc PROTO_OBJECTS := ceo.pb-c.o -PROTO_LDFLAGS := -lprotobuf-c +PROTO_LIBS := -lprotobuf-c PROTO_PROGS := op-adduser addmember addclub CONFIG_OBJECTS := config.o parser.o -CONFIG_LDFLAGS := +CONFIG_LIBS := CONFIG_PROGS := $(LDAP_PROGS) $(KRB5_PROGS) $(NET_PROGS) UTIL_OBJECTS := util.o strbuf.o UTIL_PROGS := config-test $(CONFIG_PROGS) @@ -42,7 +43,7 @@ ceo.pb-c.c ceo.pb-c.h: ceo.proto protoc-c --c_out=. ceo.proto ceod: dmaster.o dslave.o - $(CC) $(LDFLAGS) -o $@ $^ + $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) config-test: config-test.o parser.o @@ -54,19 +55,19 @@ install: install addmember addclub $(DESTDIR)$(PREFIX)/bin install ceoc op-adduser $(DESTDIR)$(PREFIX)/lib/ceod -$(NET_PROGS): LDFLAGS += $(NET_LDFLAGS) +$(NET_PROGS): LDLIBS += $(NET_LIBS) $(NET_PROGS): $(NET_OBJECTS) -$(LDAP_PROGS): LDFLAGS += $(LDAP_LDFLAGS) +$(LDAP_PROGS): LDLIBS += $(LDAP_LIBS) $(LDAP_PROGS): $(LDAP_OBJECTS) -$(KRB5_PROGS): LDFLAGS += $(KRB5_LDFLAGS) +$(KRB5_PROGS): LDLIBS += $(KRB5_LIBS) $(KRB5_PROGS): $(KRB5_OBJECTS) -$(HOME_PROGS): LDFLAGS += $(HOME_LDFLAGS) +$(HOME_PROGS): LDLIBS += $(HOME_LIBS) $(HOME_PROGS): $(HOME_OBJECTS) -$(PROTO_PROGS): LDFLAGS += $(PROTO_LDFLAGS) +$(PROTO_PROGS): LDLIBS += $(PROTO_LIBS) $(PROTO_PROGS): $(PROTO_OBJECTS) -$(CONFIG_PROGS): LDFLAGS += $(CONFIG_LDFLAGS) +$(CONFIG_PROGS): LDLIBS += $(CONFIG_LIBS) $(CONFIG_PROGS): $(CONFIG_OBJECTS) -$(UTIL_PROGS): LDFLAGS += $(UTIL_LDFLAGS) +$(UTIL_PROGS): LDLIBS += $(UTIL_LIBS) $(UTIL_PROGS): $(UTIL_OBJECTS) .PHONY: clean all From aaeca32107960022259b05736f25be250d1ce3d4 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 09:28:39 -0400 Subject: [PATCH 34/40] Make connection failure message more clear --- src/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.c b/src/net.c index dc85682..d5db0ad 100644 --- a/src/net.c +++ b/src/net.c @@ -80,7 +80,7 @@ static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strb fatal("shutdown complete"); break; case SCTP_CANT_STR_ASSOC: - fatal("cannot start association"); + fatal("connection failed (is ceod running?)"); break; } break; From e0332eecacf6bb150a351d74744b3f49af818374 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 09:34:55 -0400 Subject: [PATCH 35/40] Fix home directory error handling --- src/net.h | 1 + src/op-adduser.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/net.h b/src/net.h index 45a4a06..8674a82 100644 --- a/src/net.h +++ b/src/net.h @@ -42,5 +42,6 @@ enum { #define EKERB -2 #define ELDAP -3 +#define EHOME -4 int receive_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg); diff --git a/src/op-adduser.c b/src/op-adduser.c index 17f3602..90ab6aa 100644 --- a/src/op-adduser.c +++ b/src/op-adduser.c @@ -167,7 +167,10 @@ static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) { response_message(out, 0, "successfully created ldap group"); if ((home_stat = ceo_create_home(homedir, id, id))) - notice("successfully created home directory for %s", in->username); + response_message(out, EHOME, "unable to create home directory for %s", in->username); + else + response_message(out, 0, "successfully created home directory"); + return krb_stat || user_stat || group_stat || home_stat; } @@ -205,7 +208,9 @@ static int32_t addclub(Ceo__AddUser *in, Ceo__AddUserResponse *out) { response_message(out, 0, "successfully created ldap sudoers"); if ((home_stat = ceo_create_home(homedir, id, id))) - notice("successfully created home directory for %s", in->username); + response_message(out, EHOME, "unable to create home directory for %s", in->username); + else + response_message(out, 0, "successfully created home directory"); return user_stat || group_stat || sudo_stat || home_stat; } From 23c6c89237325cffae60cb982b14dc845471cdba Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 09:58:11 -0400 Subject: [PATCH 36/40] Fix redundant arguments to linker --- src/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 47bbc98..08aaa69 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,6 @@ CFLAGS := -g3 -O2 -Wall -Werror -DDEBUG LDFLAGS := -Wl,--as-needed INCLUDES := $(shell krb5-config --cflags) -override LDFLAGS += -std=gnu99 $(INCLUDES) override CFLAGS += -std=gnu99 $(INCLUDES) DESTDIR := @@ -43,7 +42,7 @@ ceo.pb-c.c ceo.pb-c.h: ceo.proto protoc-c --c_out=. ceo.proto ceod: dmaster.o dslave.o - $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + $(CC) $(LDFLAGS) $^ $(CFLAGS) $(LDLIBS) -o $@ config-test: config-test.o parser.o From 92652a3af09007550c7e2205d6d5da56d80ec68c Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 11:25:13 -0400 Subject: [PATCH 37/40] Install ceo daemon We need to split into different packages for the daemon and clients. --- debian/.gitignore | 6 ++++- debian/ceo-clients.manpages | 2 ++ debian/ceo-common.dirs | 1 + debian/ceo-common.install | 1 + debian/{dirs => ceo-daemon.dirs} | 2 -- debian/ceo-daemon.install | 1 + debian/ceo-gui.manpages | 1 + debian/control | 31 +++++++++++++++++++----- debian/docs | 1 - debian/install | 2 -- debian/manpages | 1 - debian/rules | 9 ++++--- etc/{accounts.cf.example => accounts.cf} | 0 etc/{kerberos.cf.example => kerberos.cf} | 0 etc/{ldap.cf.example => ldap.cf} | 0 src/Makefile | 14 ++++++++--- 16 files changed, 51 insertions(+), 21 deletions(-) create mode 100644 debian/ceo-clients.manpages create mode 100644 debian/ceo-common.dirs create mode 100644 debian/ceo-common.install rename debian/{dirs => ceo-daemon.dirs} (50%) create mode 100644 debian/ceo-daemon.install create mode 100644 debian/ceo-gui.manpages delete mode 100644 debian/docs delete mode 100644 debian/install delete mode 100644 debian/manpages rename etc/{accounts.cf.example => accounts.cf} (100%) rename etc/{kerberos.cf.example => kerberos.cf} (100%) rename etc/{ldap.cf.example => ldap.cf} (100%) diff --git a/debian/.gitignore b/debian/.gitignore index 5e861a7..ae1abc1 100644 --- a/debian/.gitignore +++ b/debian/.gitignore @@ -1,5 +1,9 @@ /ceo.substvars -/ceo +/ceo-common +/ceo-clients +/ceo-daemon +/ceo-gui /files /*.debhelper /*.debhelper.log +/*.substvars diff --git a/debian/ceo-clients.manpages b/debian/ceo-clients.manpages new file mode 100644 index 0000000..58109bc --- /dev/null +++ b/debian/ceo-clients.manpages @@ -0,0 +1,2 @@ +docs/addclub.1 +docs/addmember.1 diff --git a/debian/ceo-common.dirs b/debian/ceo-common.dirs new file mode 100644 index 0000000..41eb93b --- /dev/null +++ b/debian/ceo-common.dirs @@ -0,0 +1 @@ +etc/csc diff --git a/debian/ceo-common.install b/debian/ceo-common.install new file mode 100644 index 0000000..b17f7ba --- /dev/null +++ b/debian/ceo-common.install @@ -0,0 +1 @@ +etc/accounts.cf etc/kerberos.cf etc/ldap.cf etc/csc diff --git a/debian/dirs b/debian/ceo-daemon.dirs similarity index 50% rename from debian/dirs rename to debian/ceo-daemon.dirs index 281c9b5..46d4416 100644 --- a/debian/dirs +++ b/debian/ceo-daemon.dirs @@ -1,3 +1 @@ -usr/bin -etc/csc etc/ldap/schema diff --git a/debian/ceo-daemon.install b/debian/ceo-daemon.install new file mode 100644 index 0000000..106cad9 --- /dev/null +++ b/debian/ceo-daemon.install @@ -0,0 +1 @@ +etc/csc.schema etc/ldap/schema diff --git a/debian/ceo-gui.manpages b/debian/ceo-gui.manpages new file mode 100644 index 0000000..cc4400f --- /dev/null +++ b/debian/ceo-gui.manpages @@ -0,0 +1 @@ +docs/ceo.1 diff --git a/debian/control b/debian/control index 46595da..0cf8410 100644 --- a/debian/control +++ b/debian/control @@ -5,10 +5,29 @@ Maintainer: Systems Committee Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev, libsctp-dev, libprotobuf-c0-dev, libacl1-dev Standards-Version: 3.8.2 -Package: ceo -Architecture: any -Depends: python-ldap, python-urwid, python-sqlobject, python-psycopg2, ${python:Depends}, ${shlibs:Depends} -Description: Computer Science Club Administrative Utilities +Package: ceo-common +Architecture: all +Description: Computer Science Club Common Files This package contains the CSC Electronic Office - and other Computer Science Club administrative - programs. + common files. + +Package: ceo-gui +Architecture: all +Depends: ceo-clients, python-ldap, python-urwid, python-sqlobject, python-psycopg2, ${python:Depends}, ${shlibs:Depends} +Description: Computer Science Club Administrative GUI + This package contains the CSC Electronic Office + graphical user interface. + +Package: ceo-clients +Architecture: any +Depends: ceo-common, ${shlibs:Depends} +Description: Computer Science Club Administrative Clients + This package contains the CSC Electronic Office + client programs. + +Package: ceo-daemon +Architecture: any +Depends: ceo-common, ${shlibs:Depends} +Description: Computer Science Club Administrative Daemon + This package contains the CSC Electronic Office + daemon. diff --git a/debian/docs b/debian/docs deleted file mode 100644 index a188e06..0000000 --- a/debian/docs +++ /dev/null @@ -1 +0,0 @@ -docs/* diff --git a/debian/install b/debian/install deleted file mode 100644 index 31aaae0..0000000 --- a/debian/install +++ /dev/null @@ -1,2 +0,0 @@ -etc/accounts.cf.example etc/kerberos.cf.example etc/ldap.cf.example etc/csc -etc/csc.schema etc/ldap/schema diff --git a/debian/manpages b/debian/manpages deleted file mode 100644 index afc0dc3..0000000 --- a/debian/manpages +++ /dev/null @@ -1 +0,0 @@ -docs/*.[0-9] diff --git a/debian/rules b/debian/rules index 2c1caf1..fbd2693 100755 --- a/debian/rules +++ b/debian/rules @@ -18,13 +18,14 @@ install: build dh_testdir dh_testroot dh_installdirs - python setup.py -q install --no-compile -O0 --root=debian/ceo - $(MAKE) -C src DESTDIR=$(CURDIR)/debian/ceo PREFIX=/usr install - + python setup.py -q install --no-compile -O0 --root=debian/ceo-gui + $(MAKE) -C src DESTDIR=$(CURDIR)/debian/ceo-clients PREFIX=/usr install_clients + $(MAKE) -C src DESTDIR=$(CURDIR)/debian/ceo-daemon PREFIX=/usr install_daemon + binary-arch: build install dh_testdir dh_testroot - dh_installchangelogs + dh_installchangelogs dh_installdocs dh_installexamples dh_install diff --git a/etc/accounts.cf.example b/etc/accounts.cf similarity index 100% rename from etc/accounts.cf.example rename to etc/accounts.cf diff --git a/etc/kerberos.cf.example b/etc/kerberos.cf similarity index 100% rename from etc/kerberos.cf.example rename to etc/kerberos.cf diff --git a/etc/ldap.cf.example b/etc/ldap.cf similarity index 100% rename from etc/ldap.cf.example rename to etc/ldap.cf diff --git a/src/Makefile b/src/Makefile index 08aaa69..7d32aef 100644 --- a/src/Makefile +++ b/src/Makefile @@ -48,11 +48,17 @@ config-test: config-test.o parser.o config.o: config.h config-vars.h -install: - install -d $(DESTDIR)$(PREFIX)/sbin $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/lib/ceod - install ceod $(DESTDIR)$(PREFIX)/sbin +install_clients: + install -d $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/lib/ceod install addmember addclub $(DESTDIR)$(PREFIX)/bin - install ceoc op-adduser $(DESTDIR)$(PREFIX)/lib/ceod + install ceoc $(DESTDIR)$(PREFIX)/lib/ceod + +install_daemon: + install -d $(DESTDIR)$(PREFIX)/sbin $(DESTDIR)$(PREFIX)/lib/ceod + install ceod $(DESTDIR)$(PREFIX)/sbin + install op-adduser $(DESTDIR)$(PREFIX)/lib/ceod + +install: install_clients install_daemon $(NET_PROGS): LDLIBS += $(NET_LIBS) $(NET_PROGS): $(NET_OBJECTS) From ad30f9c47ab885a7b28af11906f96ad189dc312e Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 13:03:32 -0400 Subject: [PATCH 38/40] Insanify configuration files --- ceo/members.py | 48 +++++++++++++------------- debian/ceo-common.install | 2 +- etc/accounts.cf | 42 +++++++++++++---------- etc/kerberos.cf | 5 --- etc/ldap.cf | 14 -------- etc/library.cf | 4 +++ etc/ops/adduser | 1 + etc/spam/expired-account | 49 +++++++++++++++++++++++++++ etc/spam/new-member | 71 +++++++++++++++++++++++++++++++++++++++ src/config-vars.h | 22 ++++++------ src/homedir.c | 16 ++++----- src/homedir.h | 2 +- src/kadm.c | 4 +-- src/krb5.c | 4 +-- src/ldap.c | 10 +++--- src/op-adduser.c | 16 ++++----- src/ops.c | 2 +- 17 files changed, 211 insertions(+), 101 deletions(-) delete mode 100644 etc/kerberos.cf delete mode 100644 etc/ldap.cf create mode 100644 etc/library.cf create mode 100644 etc/ops/adduser create mode 100755 etc/spam/expired-account create mode 100755 etc/spam/new-member diff --git a/ceo/members.py b/ceo/members.py index dfcd951..fc8dd01 100644 --- a/ceo/members.py +++ b/ceo/members.py @@ -23,11 +23,9 @@ cfg = {} def configure(): """Load Members Configuration""" - string_fields = [ 'username_regex', 'shells_file', 'server_url', - 'users_base', 'groups_base', 'sasl_mech', 'sasl_realm', - 'admin_bind_keytab', 'admin_bind_userid', 'realm', - 'admin_principal', 'expired_account_email', - 'mathsoc_regex', 'mathsoc_dont_count' ] + string_fields = [ 'username_regex', 'shells_file', 'ldap_server_url', + 'ldap_users_base', 'ldap_groups_base', 'ldap_sasl_mech', 'ldap_sasl_realm', + 'expire_hook', 'mathsoc_regex', 'mathsoc_dont_count' ] numeric_fields = [ 'min_password_length' ] # read configuration file @@ -93,8 +91,8 @@ def connect(auth_callback): tries = 0 while ld is None: try: - ld = ldapi.connect_sasl(cfg['server_url'], cfg['sasl_mech'], - cfg['sasl_realm'], password) + ld = ldapi.connect_sasl(cfg['ldap_server_url'], cfg['ldap_sasl_mech'], + cfg['ldap_sasl_realm'], password) except ldap.LOCAL_ERROR, e: tries += 1 if tries > 3: @@ -172,10 +170,10 @@ def get(userid): } """ - return ldapi.lookup(ld, 'uid', userid, cfg['users_base']) + return ldapi.lookup(ld, 'uid', userid, cfg['ldap_users_base']) def uid2dn(uid): - return 'uid=%s,%s' % (ldapi.escape(uid), cfg['users_base']) + return 'uid=%s,%s' % (ldapi.escape(uid), cfg['ldap_users_base']) def list_term(term): @@ -194,7 +192,7 @@ def list_term(term): } """ - members = ldapi.search(ld, cfg['users_base'], + members = ldapi.search(ld, cfg['ldap_users_base'], '(&(objectClass=member)(term=%s))', [ term ]) return dict([(member[0], member[1]) for member in members]) @@ -214,7 +212,7 @@ def list_name(name): ] """ - members = ldapi.search(ld, cfg['users_base'], + members = ldapi.search(ld, cfg['ldap_users_base'], '(&(objectClass=member)(cn~=%s))', [ name ]) return dict([(member[0], member[1]) for member in members]) @@ -256,7 +254,7 @@ def list_all(): ] """ - members = ldapi.search(ld, cfg['users_base'], '(objectClass=member)') + members = ldapi.search(ld, cfg['ldap_users_base'], '(objectClass=member)') return dict([(member[0], member[1]) for member in members]) @@ -272,7 +270,7 @@ def list_positions(): ] """ - members = ld.search_s(cfg['users_base'], ldap.SCOPE_SUBTREE, '(position=*)') + members = ld.search_s(cfg['ldap_users_base'], ldap.SCOPE_SUBTREE, '(position=*)') positions = {} for (_, member) in members: for position in member['position']: @@ -293,7 +291,7 @@ def set_position(position, members): Example: set_position('president', ['dtbartle']) """ - res = ld.search_s(cfg['users_base'], ldap.SCOPE_SUBTREE, + res = ld.search_s(cfg['ldap_users_base'], ldap.SCOPE_SUBTREE, '(&(objectClass=member)(position=%s))' % ldapi.escape(position)) old = set([ member['uid'][0] for (_, member) in res ]) new = set(members) @@ -306,7 +304,7 @@ def set_position(position, members): for action in ['del', 'add']: for userid in mods[action]: - dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base']) + dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['ldap_users_base']) entry1 = {'position' : [position]} entry2 = {} #{'position' : []} entry = () @@ -319,8 +317,8 @@ def set_position(position, members): def change_group_member(action, group, userid): - user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base']) - group_dn = 'cn=%s,%s' % (ldapi.escape(group), cfg['groups_base']) + user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['ldap_users_base']) + group_dn = 'cn=%s,%s' % (ldapi.escape(group), cfg['ldap_groups_base']) entry1 = {'uniqueMember' : []} entry2 = {'uniqueMember' : [user_dn]} entry = [] @@ -338,7 +336,7 @@ def change_group_member(action, group, userid): ### Shells ### def get_shell(userid): - member = ldapi.lookup(ld, 'uid', userid, cfg['users_base']) + member = ldapi.lookup(ld, 'uid', userid, cfg['ldap_users_base']) if not member: raise NoSuchMember(userid) if 'loginShell' not in member: @@ -357,7 +355,7 @@ def get_shells(): def set_shell(userid, shell): if not shell in get_shells(): raise InvalidArgument("shell", shell, "is not in %s" % cfg['shells_file']) - ldapi.modify(ld, 'uid', userid, cfg['users_base'], [ (ldap.MOD_REPLACE, 'loginShell', [ shell ]) ]) + ldapi.modify(ld, 'uid', userid, cfg['ldap_users_base'], [ (ldap.MOD_REPLACE, 'loginShell', [ shell ]) ]) @@ -414,7 +412,7 @@ def register(userid, term_list): Example: register(3349, ["w2007", "s2007"]) """ - user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base']) + user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['ldap_users_base']) if type(term_list) in (str, unicode): term_list = [ term_list ] @@ -446,7 +444,7 @@ def register(userid, term_list): def register_nonmember(userid, term_list): """Registers a non-member for one or more terms.""" - user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base']) + user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['ldap_users_base']) if type(term_list) in (str, unicode): term_list = [ term_list ] @@ -505,7 +503,7 @@ def group_members(group): Returns a list of group members """ - group = ldapi.lookup(ld, 'cn', group, cfg['groups_base']) + group = ldapi.lookup(ld, 'cn', group, cfg['ldap_groups_base']) if group and 'uniqueMember' in group: r = re.compile('^uid=([^,]*)') @@ -513,11 +511,11 @@ def group_members(group): return [] def expired_accounts(): - members = ldapi.search(ld, cfg['users_base'], + members = ldapi.search(ld, cfg['ldap_users_base'], '(&(objectClass=member)(!(|(term=%s)(nonMemberTerm=%s))))' % (terms.current(), terms.current())) return dict([(member[0], member[1]) for member in members]) def send_account_expired_email(name, email): - args = [ cfg['expired_account_email'], name, email ] - os.spawnv(os.P_WAIT, cfg['expired_account_email'], args) + args = [ cfg['expire_hook'], name, email ] + os.spawnv(os.P_WAIT, cfg['expire_hook'], args) diff --git a/debian/ceo-common.install b/debian/ceo-common.install index b17f7ba..5561095 100644 --- a/debian/ceo-common.install +++ b/debian/ceo-common.install @@ -1 +1 @@ -etc/accounts.cf etc/kerberos.cf etc/ldap.cf etc/csc +etc/accounts.cf etc/library.cf etc/ops etc/spam etc/csc diff --git a/etc/accounts.cf b/etc/accounts.cf index a9b9819..8f7f46c 100644 --- a/etc/accounts.cf +++ b/etc/accounts.cf @@ -1,17 +1,13 @@ # /etc/csc/accounts.cf: CSC Accounts Configuration -include /etc/csc/ldap.cf -include /etc/csc/kerberos.cf - ### Member Account Options ### member_min_id = 20001 member_max_id = 29999 member_shell = "/bin/bash" member_home = "/users" -#member_home_acl = "u::rwx,g::rx,o::rx" -#member_home_dacl = -member_home_acl = +member_home_acl = "u::rwx,g::rx,o::rx" +member_home_skel = "/users/skel" ### Club Account Options ### @@ -20,27 +16,37 @@ club_max_id = 39999 club_shell = "/bin/bash" club_home = "/users" club_home_acl = "A+group:%s:rwpRAxaWdDcCs:fd:allow" +club_home_skel = "/users/skel" -### Administrative Account Options +### Administrative Account Options ### admin_min_id = 10001 admin_max_id = 19999 -admin_shell = "/bin/bash" -admin_home = "/users" -### Home Directory Options ### +### LDAP Options ### -skeleton_dir = "/users/skel" -homedir_mode = "0755" -refquota = "4G" +ldap_server_url = "ldaps://ldap-master.csclub.uwaterloo.ca" +ldap_users_base = "ou=People,dc=csclub,dc=uwaterloo,dc=ca" +ldap_groups_base = "ou=Group,dc=csclub,dc=uwaterloo,dc=ca" +ldap_sudo_base = "ou=SUDOers,dc=csclub,dc=uwaterloo,dc=ca" +ldap_sasl_mech = "GSSAPI" +ldap_sasl_realm = "CSCLUB.UWATERLOO.CA" +ldap_admin_principal = "ceod/admin@CSCLUB.UWATERLOO.CA" -### Validation Tuning ### +### Kerberos Options ### + +krb5_realm = "CSCLUB.UWATERLOO.CA" +krb5_admin_principal = "ceod/admin@CSCLUB.UWATERLOO.CA" + +### Spam ### + +notify_hook = "/etc/csc/spam/new-member" +expire_hook = "/etc/csc/spam/expired-account" + +### Miscellaneous ### username_regex = "^[a-z][-a-z0-9]*$" min_password_length = 4 shells_file = "/etc/shells" -privileged_group = "staff" -notify_hook = "/etc/csc/notify-hook" -expired_account_email = "/etc/csc/expired-account" mathsoc_regex = ".*(mat/|vpa/se|computer science|math).*" -mathsoc_dont_count = "cpdohert dlgawley dtbartle mbiggs saforres tmyklebu" +mathsoc_dont_count = "cpdohert dlgawley dtbartle mbiggs saforres tmyklebu mgregson rridge dbelange" diff --git a/etc/kerberos.cf b/etc/kerberos.cf deleted file mode 100644 index 19ad876..0000000 --- a/etc/kerberos.cf +++ /dev/null @@ -1,5 +0,0 @@ -# /etc/csc/kerberos.cf: CSC Kerberos Administration Configuration - -realm = "CSCLUB.UWATERLOO.CA" -admin_principal = "ceo/admin@CSCLUB.UWATERLOO.CA" -admin_keytab = "/etc/csc/ceo.keytab" diff --git a/etc/ldap.cf b/etc/ldap.cf deleted file mode 100644 index 29755da..0000000 --- a/etc/ldap.cf +++ /dev/null @@ -1,14 +0,0 @@ -# /etc/csc/ldap.cf: CSC LDAP Configuration - -server_url = "ldaps:///" - -users_base = "ou=People,dc=csclub,dc=uwaterloo,dc=ca" -groups_base = "ou=Group,dc=csclub,dc=uwaterloo,dc=ca" -sudo_base = "ou=SUDOers,dc=csclub,dc=uwaterloo,dc=ca" - -admin_bind_dn = -admin_bind_keytab = "/etc/csc/ceo.keytab" -admin_bind_userid = "ceo" - -sasl_mech = "GSSAPI" -sasl_realm = "CSCLUB.UWATERLOO.CA" diff --git a/etc/library.cf b/etc/library.cf new file mode 100644 index 0000000..41d11d8 --- /dev/null +++ b/etc/library.cf @@ -0,0 +1,4 @@ +# /etc/csc/library.cf: Library Config + +library_connect_string = "postgres://librarian:PWPWPWPWPWPWPWPWPWPW@127.0.0.1/library" +aws_account_key = "KEYKEYKEYKEYKEYKEYKY" diff --git a/etc/ops/adduser b/etc/ops/adduser new file mode 100644 index 0000000..71ee80b --- /dev/null +++ b/etc/ops/adduser @@ -0,0 +1 @@ +ginseng adduser 0x01 diff --git a/etc/spam/expired-account b/etc/spam/expired-account new file mode 100755 index 0000000..a3884ea --- /dev/null +++ b/etc/spam/expired-account @@ -0,0 +1,49 @@ +#!/bin/sh + +name=$1 +email=$2 +shift 2 + +tmp="$(tempfile)" +trap "rm $tmp" 0 +exec >"$tmp" + +echo "From: Computer Science Club " +echo "Reply-to: CSClub Exec " +echo "To: $name <$email>" +echo "Subject: [CSClub] Account Expiration" +echo "" +echo "Hello, + +We noticed that your Computer Science Club membership has expired. We would +like to remind you of the many benefits of being a member of the club: + +* 4 GiB of disk quota +* Web space +* Email address +* Shell account +* Access to our library + +If you would like to renew your membership (the fee is \$2 per term), we have +various methods of doing so: + +* Come by our office (MC 3036) +* Send us a PayPal donation and send us the transaction id; see + http://csclub.uwaterloo.ca/about/donations for details +* Mail us a cheque; here's our address: + Computer Science Club + Math & Computer 3036/3037 + University of Waterloo + 200 University Avenue West + Waterloo, ON N3L 3G1 + Canada + +If you have any questions, feel free to contact us by phone at +(519) 888-4567 x33870, or by email at exec@csclub.uwaterloo.ca. + +Regards, + +The Computer Science Club" + +exec >&- 2>&- +/usr/sbin/sendmail -t -f "ceo@csclub.uwaterloo.ca" < "$tmp" diff --git a/etc/spam/new-member b/etc/spam/new-member new file mode 100755 index 0000000..a6851b3 --- /dev/null +++ b/etc/spam/new-member @@ -0,0 +1,71 @@ +#!/bin/bash -p + +# This is a privileged script. +IFS=$' \t\n' +PATH=/usr/bin:/bin +unset ENV BASH_ENV CDPATH +umask 077 + +prog=$1 +auth=$2 +shift 2 + +tmp="$(tempfile)" +trap "rm $tmp" 0 +exec >"$tmp" + +authrn="$(getent passwd "$auth" | awk -F: '{ print $5 }' | sed -e 's/,.*//')" + +h_from="$prog " +h_to="Membership and Accounts " +h_cc="$authrn <$auth@csclub.uwaterloo.ca>" + +if test "$prog" = addmember; then + user=$1 name=$2 dept=$3 status=$4; shift 4 + subj="New Member: $user" + test -z "$dept" && dept="things unknown" + body="Name: $name +Account: $user +Program: $dept +Added by: $auth" + +elif test "$prog" = addclub; then + user=$1 name=$2 status=$4; shift 4 + subj="New Club Account: $user" + body="Club: $name +Account: $user +Added by: $auth" + +else + exit 1 +fi + +output=$(cat) + +if test "$status" = "failure"; then + subj="$subj (FAILURES)" +fi + +echo "From: $h_from" +echo "To: $h_to" +echo "Cc: $h_cc" +echo "X-Auth-User: $auth" +echo "X-New-User: $user" +echo "X-New-Name: $name" +echo "Subject: $subj" +echo +echo "$body" | fmt -s +echo + +if test "$status" = "success"; then + echo all failures went undetected +elif test -n "$output"; then + echo "$output" +fi + +echo +echo Your Friend, +echo "$prog" + +exec >&2 +env - /usr/sbin/sendmail -t -f "ceo@csclub.uwaterloo.ca" < "$tmp" diff --git a/src/config-vars.h b/src/config-vars.h index 36f7a4c..0380dc4 100644 --- a/src/config-vars.h +++ b/src/config-vars.h @@ -1,24 +1,24 @@ -CONFIG_STR(server_url) - -CONFIG_STR(users_base) -CONFIG_STR(groups_base) -CONFIG_STR(sudo_base) - -CONFIG_STR(skeleton_dir) - CONFIG_STR(member_shell) CONFIG_INT(member_min_id) CONFIG_INT(member_max_id) CONFIG_STR(member_home) +CONFIG_STR(member_home_skel) CONFIG_STR(club_shell) CONFIG_INT(club_min_id) CONFIG_INT(club_max_id) CONFIG_STR(club_home) +CONFIG_STR(club_home_skel) CONFIG_STR(notify_hook) -CONFIG_STR(realm) +CONFIG_STR(krb5_realm) +CONFIG_STR(krb5_admin_principal) -CONFIG_STR(admin_principal) -CONFIG_STR(admin_bind_userid) +CONFIG_STR(ldap_server_url) +CONFIG_STR(ldap_users_base) +CONFIG_STR(ldap_groups_base) +CONFIG_STR(ldap_sudo_base) +CONFIG_STR(ldap_sasl_mech) +CONFIG_STR(ldap_sasl_realm) +CONFIG_STR(ldap_admin_principal) diff --git a/src/homedir.c b/src/homedir.c index 83772df..b808fcd 100644 --- a/src/homedir.c +++ b/src/homedir.c @@ -11,9 +11,9 @@ #include "util.h" #include "config.h" -int ceo_create_home(char *homedir, uid_t uid, gid_t gid) { +int ceo_create_home(char *homedir, char *skel, uid_t uid, gid_t gid) { int mask; - DIR *skel; + DIR *skeldir; struct dirent *skelent; mask = umask(0); @@ -23,20 +23,20 @@ int ceo_create_home(char *homedir, uid_t uid, gid_t gid) { return -1; } - skel = opendir(skeleton_dir); - if (!skel) { - errorpe("failed to open %s", skeleton_dir); + skeldir = opendir(skel); + if (!skeldir) { + errorpe("failed to open %s", skel); return -1; } - while ((skelent = readdir(skel))) { + while ((skelent = readdir(skeldir))) { struct stat sb; char src[PATH_MAX], dest[PATH_MAX]; if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, "..")) continue; - snprintf(src, sizeof(src), "%s/%s", skeleton_dir, skelent->d_name); + snprintf(src, sizeof(src), "%s/%s", skel, skelent->d_name); snprintf(dest, sizeof(dest), "%s/%s", homedir, skelent->d_name); lstat(src, &sb); @@ -108,7 +108,7 @@ int ceo_create_home(char *homedir, uid_t uid, gid_t gid) { } } - closedir(skel); + closedir(skeldir); if (chown(homedir, uid, gid)) { errorpe("failed to chown %s", homedir); diff --git a/src/homedir.h b/src/homedir.h index 8bc04bf..0637867 100644 --- a/src/homedir.h +++ b/src/homedir.h @@ -1,3 +1,3 @@ #include -int ceo_create_home(char *homedir, uid_t uid, gid_t gid); +int ceo_create_home(char *homedir, char *skel, uid_t uid, gid_t gid); diff --git a/src/kadm.c b/src/kadm.c index 5075d52..fd64316 100644 --- a/src/kadm.c +++ b/src/kadm.c @@ -14,9 +14,9 @@ void ceo_kadm_init() { kadm5_config_params params; memset((void *) ¶ms, 0, sizeof(params)); - debug("kadmin: initializing using keytab for %s", admin_principal); + debug("kadmin: initializing using keytab for %s", krb5_admin_principal); - retval = kadm5_init_with_skey(admin_principal, NULL, + retval = kadm5_init_with_skey(krb5_admin_principal, NULL, KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL, &handle); if (retval || !handle) { diff --git a/src/krb5.c b/src/krb5.c index 8fedade..d045733 100644 --- a/src/krb5.c +++ b/src/krb5.c @@ -41,7 +41,7 @@ void ceo_krb5_init() { if (retval) com_err(prog, retval, "while initializing krb5"); - retval = krb5_set_default_realm(context, realm); + retval = krb5_set_default_realm(context, krb5_realm); if (retval) com_err(prog, retval, "while setting default realm"); } @@ -59,7 +59,7 @@ void ceo_krb5_auth(char *principal) { debug("krb5: getting TGT using keytab for %s", principal); if ((retval = krb5_parse_name(context, principal, &princ))) - com_err(prog, retval, "while resolving user %s", admin_bind_userid); + com_err(prog, retval, "while resolving user %s", principal); if ((retval = krb5_cc_default(context, &cache))) com_err(prog, retval, "while resolving credentials cache"); diff --git a/src/ldap.c b/src/ldap.c index 4c269d6..2201eec 100644 --- a/src/ldap.c +++ b/src/ldap.c @@ -277,7 +277,7 @@ int ceo_new_uid(int min, int max) { continue; snprintf(filter, sizeof(filter), "(|(uidNumber=%d)(gidNumber=%d))", i, i); - if (ldap_search_s(ld, users_base, LDAP_SCOPE_SUBTREE, filter, attrs, 1, &res) != LDAP_SUCCESS) { + if (ldap_search_s(ld, ldap_users_base, LDAP_SCOPE_SUBTREE, filter, attrs, 1, &res) != LDAP_SUCCESS) { ldap_err("firstuid"); return -1; } @@ -306,7 +306,7 @@ int ceo_user_exists(char *uid) { snprintf(filter, sizeof(filter), "uid=%s", uid); - if (ldap_search_s(ld, users_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg) != LDAP_SUCCESS) { + if (ldap_search_s(ld, ldap_users_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg) != LDAP_SUCCESS) { ldap_err("user_exists"); return -1; } @@ -328,7 +328,7 @@ int ceo_group_exists(char *cn) { snprintf(filter, sizeof(filter), "cn=%s", cn); - if (ldap_search_s(ld, groups_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg) != LDAP_SUCCESS) { + if (ldap_search_s(ld, ldap_groups_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg) != LDAP_SUCCESS) { ldap_err("group_exists"); return -1; } @@ -362,10 +362,10 @@ void ceo_ldap_init() { int proto = LDAP_DEFAULT_PROTOCOL; const char *sasl_mech = "GSSAPI"; - if (!admin_bind_userid) + if (!ldap_admin_principal) fatal("not configured"); - if (ldap_initialize(&ld, server_url) != LDAP_SUCCESS) + if (ldap_initialize(&ld, ldap_server_url) != LDAP_SUCCESS) ldap_fatal("ldap_initialize"); if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &proto) != LDAP_OPT_SUCCESS) diff --git a/src/op-adduser.c b/src/op-adduser.c index 90ab6aa..5ad2fae 100644 --- a/src/op-adduser.c +++ b/src/op-adduser.c @@ -154,19 +154,19 @@ static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) { return response_message(out, EKERB, "unable to create kerberos principal %s", in->username); response_message(out, 0, "successfully created principal"); - if ((user_stat = ceo_add_user(in->username, users_base, "member", in->realname, homedir, + if ((user_stat = ceo_add_user(in->username, ldap_users_base, "member", in->realname, homedir, member_shell, id, "program", in->program, NULL))) return response_message(out, ELDAP, "unable to create ldap account %s", in->username); response_message(out, 0, "successfully created ldap account"); /* errors that occur after this point are not fatal */ - if ((group_stat = ceo_add_group(in->username, groups_base, id))) + if ((group_stat = ceo_add_group(in->username, ldap_groups_base, id))) response_message(out, ELDAP, "unable to create ldap group %s", in->username); else response_message(out, 0, "successfully created ldap group"); - if ((home_stat = ceo_create_home(homedir, id, id))) + if ((home_stat = ceo_create_home(homedir, member_home_skel, id, id))) response_message(out, EHOME, "unable to create home directory for %s", in->username); else response_message(out, 0, "successfully created home directory"); @@ -190,24 +190,24 @@ static int32_t addclub(Ceo__AddUser *in, Ceo__AddUserResponse *out) { if ((krb_stat = ceo_del_princ(in->username))) return response_message(out, EKERB, "unable to clear principal %s", in->username); - if ((user_stat = ceo_add_user(in->username, users_base, "club", in->realname, homedir, + if ((user_stat = ceo_add_user(in->username, ldap_users_base, "club", in->realname, homedir, club_shell, id, NULL))) return response_message(out, ELDAP, "unable to create ldap account %s", in->username); response_message(out, 0, "successfully created ldap account"); /* errors that occur after this point are not fatal */ - if ((group_stat = ceo_add_group(in->username, groups_base, id))) + if ((group_stat = ceo_add_group(in->username, ldap_groups_base, id))) response_message(out, ELDAP, "unable to create ldap group %s", in->username); else response_message(out, 0, "successfully created ldap group"); - if ((sudo_stat = ceo_add_group_sudo(in->username, sudo_base))) + if ((sudo_stat = ceo_add_group_sudo(in->username, ldap_sudo_base))) response_message(out, ELDAP, "unable to create ldap sudoers %s", in->username); else response_message(out, 0, "successfully created ldap sudoers"); - if ((home_stat = ceo_create_home(homedir, id, id))) + if ((home_stat = ceo_create_home(homedir, club_home_skel, id, id))) response_message(out, EHOME, "unable to create home directory for %s", in->username); else response_message(out, 0, "successfully created home directory"); @@ -282,7 +282,7 @@ int main(int argc, char *argv[]) { fatalpe("setenv"); ceo_krb5_init(); - ceo_krb5_auth(admin_bind_userid); + ceo_krb5_auth(ldap_admin_principal); ceo_ldap_init(); ceo_kadm_init(); diff --git a/src/ops.c b/src/ops.c index 857f633..b86ef43 100644 --- a/src/ops.c +++ b/src/ops.c @@ -68,7 +68,7 @@ void setup_ops(void) { op_dir = getenv("CEO_LIB_DIR") ?: default_op_dir; - if (snprintf(op_config_dir, sizeof(op_config_dir), "%s/%s", config_dir, "ops.d") >= sizeof(op_config_dir)) + if (snprintf(op_config_dir, sizeof(op_config_dir), "%s/%s", config_dir, "ops") >= sizeof(op_config_dir)) fatal("ops dir path too long"); dp = opendir(op_config_dir); From 1c8e24773230828bad89680fd4583562acb8c231 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 16:14:52 -0400 Subject: [PATCH 39/40] Allow digits in variable names --- src/parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser.c b/src/parser.c index 9b8d3e3..7d462ea 100644 --- a/src/parser.c +++ b/src/parser.c @@ -53,7 +53,7 @@ static void parse_name(struct config_file *file, char *name, size_t maxlen) { break; } - if (!isalpha(c) && c != '_' && c != '-') { + if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') { unparse_char(file, c); break; } From 778efc71aa83c3d1cc1ca489276aa0307e4a8103 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 29 Jul 2009 16:42:56 -0400 Subject: [PATCH 40/40] Updates for LDAP-backed Kerberos Principals are now created implicitly when the LDAP entry for a user is added. We add the keys by "changing" the password from nonexistent to existent. --- src/kadm.c | 8 ++++---- src/ldap.c | 20 +++++++++++++++++--- src/ldap.h | 2 +- src/op-adduser.c | 17 +++++++++++------ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/kadm.c b/src/kadm.c index fd64316..90790e9 100644 --- a/src/kadm.c +++ b/src/kadm.c @@ -32,22 +32,22 @@ void ceo_kadm_cleanup() { int ceo_add_princ(char *user, char *password) { krb5_error_code retval; - kadm5_principal_ent_rec princ; + krb5_principal princ; memset((void *) &princ, 0, sizeof(princ)); debug("kadmin: adding principal %s", user); - if ((retval = krb5_parse_name(context, user, &princ.principal))) { + if ((retval = krb5_parse_name(context, user, &princ))) { com_err(prog, retval, "while parsing principal name"); return retval; } - if ((retval = kadm5_create_principal(handle, &princ, KADM5_PRINCIPAL, password))) { + if ((retval = kadm5_chpass_principal(handle, princ, password))) { com_err(prog, retval, "while creating principal"); return retval; } - krb5_free_principal(context, princ.principal); + krb5_free_principal(context, princ); return 0; } diff --git a/src/ldap.c b/src/ldap.c index 2201eec..2154036 100644 --- a/src/ldap.c +++ b/src/ldap.c @@ -170,7 +170,7 @@ int ceo_add_group_sudo(char *group, char *basedn) { return ret; } -int ceo_add_user(char *uid, char *basedn, char *objclass, char *cn, char *home, char *shell, int no, ...) { +int ceo_add_user(char *uid, char *basedn, char *objclass, char *cn, char *home, char *principal, char *shell, int no, ...) { va_list args; if (!uid || !basedn || !cn || !home || !shell) @@ -179,13 +179,19 @@ int ceo_add_user(char *uid, char *basedn, char *objclass, char *cn, char *home, LDAPMod *mods[16]; int i = -1; int ret = 0; + int classes = 4; mods[++i] = xmalloc(sizeof(LDAPMod)); mods[i]->mod_op = LDAP_MOD_ADD; mods[i]->mod_type = "objectClass"; - char *objectClasses[] = { "top", "account", "posixAccount", "shadowAccount", NULL, NULL }; + char *objectClasses[] = { "top", "account", "posixAccount", "shadowAccount", NULL, NULL, NULL, NULL }; if (objclass != NULL) - objectClasses[4] = objclass; + objectClasses[classes++] = objclass; + if (principal) { + objectClasses[classes++] = "krbPrincipalAux"; + objectClasses[classes++] = "krbTicketPolicyAux"; + + } mods[i]->mod_values = objectClasses; mods[++i] = xmalloc(sizeof(LDAPMod)); @@ -225,6 +231,14 @@ int ceo_add_user(char *uid, char *basedn, char *objclass, char *cn, char *home, char *homeDirectory[] = { home, NULL }; mods[i]->mod_values = homeDirectory; + if (principal) { + mods[++i] = xmalloc(sizeof(LDAPMod)); + mods[i]->mod_op = LDAP_MOD_ADD; + mods[i]->mod_type = "krbPrincipalName"; + char *krbPrincipalName[] = { principal, NULL }; + mods[i]->mod_values = krbPrincipalName; + } + va_start(args, no); char *attr; while ((attr = va_arg(args, char *))) { diff --git a/src/ldap.h b/src/ldap.h index b29b68b..5a2d3f5 100644 --- a/src/ldap.h +++ b/src/ldap.h @@ -1,6 +1,6 @@ #define LDAP_DEFAULT_PROTOCOL LDAP_VERSION3 -int ceo_add_user(char *, char *, char *, char *, char *, char *, int, ...); +int ceo_add_user(char *, char *, char *, char *, char *, char *, char *, int, ...); int ceo_add_group(char *, char *, int); int ceo_add_group_sudo(char *, char *); int ceo_new_uid(int, int); diff --git a/src/op-adduser.c b/src/op-adduser.c index 5ad2fae..b1465cc 100644 --- a/src/op-adduser.c +++ b/src/op-adduser.c @@ -137,9 +137,14 @@ static void adduser_spam(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *clie static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) { char homedir[1024]; + char principal[1024]; int user_stat, group_stat, krb_stat, home_stat; int id; + if (snprintf(principal, sizeof(principal), "%s@%s", + in->username, krb5_realm) >= sizeof(principal)) + fatal("principal overflow"); + if (snprintf(homedir, sizeof(homedir), "%s/%s", member_home, in->username) >= sizeof(homedir)) fatal("homedir overflow"); @@ -150,17 +155,17 @@ static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) { if ((krb_stat = ceo_del_princ(in->username))) return response_message(out, EEXIST, "unable to overwrite orphaned kerberos principal %s", in->username); - if ((krb_stat = ceo_add_princ(in->username, in->password))) - return response_message(out, EKERB, "unable to create kerberos principal %s", in->username); - response_message(out, 0, "successfully created principal"); - - if ((user_stat = ceo_add_user(in->username, ldap_users_base, "member", in->realname, homedir, + if ((user_stat = ceo_add_user(in->username, ldap_users_base, "member", in->realname, homedir, principal, member_shell, id, "program", in->program, NULL))) return response_message(out, ELDAP, "unable to create ldap account %s", in->username); response_message(out, 0, "successfully created ldap account"); /* errors that occur after this point are not fatal */ + if ((krb_stat = ceo_add_princ(in->username, in->password))) + return response_message(out, EKERB, "unable to create kerberos principal %s", in->username); + response_message(out, 0, "successfully created principal"); + if ((group_stat = ceo_add_group(in->username, ldap_groups_base, id))) response_message(out, ELDAP, "unable to create ldap group %s", in->username); else @@ -191,7 +196,7 @@ static int32_t addclub(Ceo__AddUser *in, Ceo__AddUserResponse *out) { return response_message(out, EKERB, "unable to clear principal %s", in->username); if ((user_stat = ceo_add_user(in->username, ldap_users_base, "club", in->realname, homedir, - club_shell, id, NULL))) + NULL, club_shell, id, NULL))) return response_message(out, ELDAP, "unable to create ldap account %s", in->username); response_message(out, 0, "successfully created ldap account");