From c0dfe79ba578d62a991b0a829d7e0f670a445109 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mon, 12 Oct 2009 15:38:29 +0200 Subject: enable debugging of krb5_child --- server/Makefile.am | 2 + server/providers/krb5/krb5_auth.c | 101 ++++++++++++++++++++++++++++++++++++- server/providers/krb5/krb5_auth.h | 1 + server/providers/krb5/krb5_child.c | 44 +++++++++++++++- server/util/debug.c | 40 +++++++++++++-- server/util/util.h | 2 + 6 files changed, 182 insertions(+), 8 deletions(-) diff --git a/server/Makefile.am b/server/Makefile.am index 70b64b8ad..9adce0cb7 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -471,9 +471,11 @@ krb5_child_SOURCES = \ providers/krb5/krb5_child.c krb5_child_CFLAGS = \ $(AM_CFLAGS) \ + $(POPT_CFLAGS) \ $(KRB5_CFLAGS) krb5_child_LDADD = \ $(TALLOC_LIBS) \ + $(POPT_LIBS) \ $(KRB5_LIBS) memberof_la_SOURCES = \ diff --git a/server/providers/krb5/krb5_auth.c b/server/providers/krb5/krb5_auth.c index 91f91969e..4d98b9312 100644 --- a/server/providers/krb5/krb5_auth.c +++ b/server/providers/krb5/krb5_auth.c @@ -327,6 +327,76 @@ static void wait_for_child_handler(struct tevent_context *ev, return; } +static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx, + struct krb5child_req *kr, + char ***_argv) +{ + uint_t argc = 3; /* program name, debug_level and NULL */ + char ** argv; + errno_t ret = EINVAL; + + /* Save the current state in case an interrupt changes it */ + bool child_debug_to_file = debug_to_file; + bool child_debug_timestamps = debug_timestamps; + + if (child_debug_to_file) argc++; + if (child_debug_timestamps) argc++; + + /* program name, debug_level, + * debug_to_file, debug_timestamps + * and NULL */ + argv = talloc_array(mem_ctx, char *, argc); + if (argv == NULL) { + DEBUG(1, ("talloc_array failed.\n")); + return ENOMEM; + } + + argv[--argc] = NULL; + + argv[--argc] = talloc_asprintf(argv, "--debug-level=%d", + debug_level); + if (argv[argc] == NULL) { + ret = ENOMEM; + goto fail; + } + + if (child_debug_to_file) { + argv[--argc] = talloc_asprintf(argv, "--debug-fd=%d", + kr->krb5_ctx->child_debug_fd); + if (argv[argc] == NULL) { + ret = ENOMEM; + goto fail; + } + } + + if (child_debug_timestamps) { + argv[--argc] = talloc_strdup(argv, "--debug-timestamps"); + if (argv[argc] == NULL) { + ret = ENOMEM; + goto fail; + } + } + + argv[--argc] = talloc_strdup(argv, KRB5_CHILD); + if (argv[argc] == NULL) { + ret = ENOMEM; + goto fail; + } + + if (argc != 0) { + ret = EINVAL; + goto fail; + } + + *_argv = argv; + + return EOK; + +fail: + talloc_free(argv); + return ret; +} + static errno_t fork_child(struct krb5child_req *kr) { int pipefd_to_child[2]; @@ -334,6 +404,7 @@ static errno_t fork_child(struct krb5child_req *kr) pid_t pid; int ret; errno_t err; + char **argv; ret = pipe(pipefd_from_child); if (ret == -1) { @@ -383,10 +454,16 @@ static errno_t fork_child(struct krb5child_req *kr) return err; } - ret = execl(KRB5_CHILD, KRB5_CHILD, NULL); + ret = prepare_child_argv(kr, kr, &argv); + if (ret != EOK) { + DEBUG(1, ("prepare_child_argv.\n")); + return ret; + } + + ret = execv(KRB5_CHILD, argv); if (ret == -1) { err = errno; - DEBUG(1, ("execl failed [%d][%s].\n", errno, strerror(errno))); + DEBUG(1, ("execv failed [%d][%s].\n", errno, strerror(errno))); return err; } } else if (pid > 0) { /* parent */ @@ -912,6 +989,8 @@ int sssm_krb5_auth_init(struct be_ctx *bectx, int ret; struct tevent_signal *sige; struct stat stat_buf; + unsigned v; + FILE *debug_filep; ctx = talloc_zero(bectx, struct krb5_ctx); if (!ctx) { @@ -1015,6 +1094,24 @@ int sssm_krb5_auth_init(struct be_ctx *bectx, goto fail; } + if (debug_to_file != 0) { + ret = open_debug_file_ex("krb5_child", &debug_filep); + if (ret != EOK) { + DEBUG(0, ("Error setting up logging (%d) [%s]\n", + ret, strerror(ret))); + goto fail; + } + + ctx->child_debug_fd = fileno(debug_filep); + if (ctx->child_debug_fd == -1) { + DEBUG(0, ("fileno failed [%d][%s]\n", errno, strerror(errno))); + ret = errno; + goto fail; + } + + v = fcntl(ctx->child_debug_fd, F_GETFD, 0); + fcntl(ctx->child_debug_fd, F_SETFD, v & ~FD_CLOEXEC); + } *ops = &krb5_auth_ops; *pvt_auth_data = ctx; diff --git a/server/providers/krb5/krb5_auth.h b/server/providers/krb5/krb5_auth.h index e70f5d3aa..1fd7c5897 100644 --- a/server/providers/krb5/krb5_auth.h +++ b/server/providers/krb5/krb5_auth.h @@ -92,6 +92,7 @@ struct krb5_ctx { char *ccache_dir; char *ccname_template; int auth_timeout; + int child_debug_fd; }; #endif /* __KRB5_AUTH_H__ */ diff --git a/server/providers/krb5/krb5_child.c b/server/providers/krb5/krb5_child.c index 9b1be9c95..4e681b979 100644 --- a/server/providers/krb5/krb5_child.c +++ b/server/providers/krb5/krb5_child.c @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -641,7 +642,7 @@ failed: return kerr; } -int main(int argc, char *argv[]) +int main(int argc, const char *argv[]) { uint8_t *buf = NULL; int ret; @@ -649,10 +650,49 @@ int main(int argc, char *argv[]) struct pam_data *pd = NULL; struct krb5_req *kr = NULL; char *ccname; + int opt; + poptContext pc; + int debug_fd = -1; + + struct poptOption long_options[] = { + POPT_AUTOHELP + {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0, + "Debug level", NULL}, + {"debug-timestamps", 0, POPT_ARG_NONE, &debug_timestamps, 0, + "Add debug timestamps", NULL}, + {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0, + "Add debug timestamps", NULL}, + POPT_TABLEEND + }; + + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + _exit(-1); + } + } - debug_prg_name = argv[0]; + poptFreeContext(pc); pd = talloc(NULL, struct pam_data); + if (pd == NULL) { + DEBUG(1, ("malloc failed.\n")); + _exit(-1); + } + + debug_prg_name = talloc_asprintf(pd, "[sssd[krb5_child[%d]]]", getpid()); + + if (debug_fd != -1) { + ret = set_debug_file_from_fd(debug_fd); + if (ret != EOK) { + DEBUG(1, ("set_debug_file_from_fd failed.\n")); + } + } buf = talloc_size(pd, sizeof(uint8_t)*IN_BUF_SIZE); if (buf == NULL) { diff --git a/server/util/debug.c b/server/util/debug.c index c6aa27c92..862367ce5 100644 --- a/server/util/debug.c +++ b/server/util/debug.c @@ -37,6 +37,22 @@ int debug_to_file = 0; const char *debug_log_file = "sssd"; FILE *debug_file = NULL; + +errno_t set_debug_file_from_fd(const int fd) +{ + FILE *dummy; + + dummy = fdopen(fd, "a"); + if (dummy == NULL) { + DEBUG(1, ("fdopen failed [%d][%s].\n", errno, strerror(errno))); + return errno; + } + + debug_file = dummy; + + return EOK; +} + void debug_fn(const char *format, ...) { va_list ap; @@ -99,19 +115,26 @@ void ldb_debug_messages(void *context, enum ldb_debug_level level, free(message); } -int open_debug_file() +int open_debug_file_ex(const char *filename, FILE **filep) { FILE *f = NULL; char *logpath; + const char *log_file; mode_t old_umask; int ret; - ret = asprintf(&logpath, "%s/%s.log", LOG_PATH, debug_log_file); + if (filename == NULL) { + log_file = debug_log_file; + } else { + log_file = filename; + } + + ret = asprintf(&logpath, "%s/%s.log", LOG_PATH, log_file); if (ret == -1) { return ENOMEM; } - if (debug_file) fclose(debug_file); + if (debug_file && !filep) fclose(debug_file); old_umask = umask(0177); f = fopen(logpath, "a"); @@ -121,7 +144,16 @@ int open_debug_file() } umask(old_umask); - debug_file = f; + if (filep == NULL) { + debug_file = f; + } else { + *filep = f; + } free(logpath); return EOK; } + +int open_debug_file(void) +{ + return open_debug_file_ex(NULL, NULL); +} diff --git a/server/util/util.h b/server/util/util.h index b7deb8540..a9d255328 100644 --- a/server/util/util.h +++ b/server/util/util.h @@ -46,6 +46,7 @@ extern int debug_timestamps; extern int debug_to_file; extern const char *debug_log_file; void debug_fn(const char *format, ...); +errno_t set_debug_file_from_fd(const int fd); #define SSSD_DEBUG_OPTS \ {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0, \ @@ -137,6 +138,7 @@ void debug_fn(const char *format, ...); /* From debug.c */ void ldb_debug_messages(void *context, enum ldb_debug_level level, const char *fmt, va_list ap); +int open_debug_file_ex(const char *filename, FILE **filep); int open_debug_file(void); /* from server.c */ -- cgit