summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/Makefile.am2
-rw-r--r--server/providers/krb5/krb5_auth.c101
-rw-r--r--server/providers/krb5/krb5_auth.h1
-rw-r--r--server/providers/krb5/krb5_child.c44
-rw-r--r--server/util/debug.c40
-rw-r--r--server/util/util.h2
6 files changed, 182 insertions, 8 deletions
diff --git a/server/Makefile.am b/server/Makefile.am
index 70b64b8a..9adce0cb 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 91f91969..4d98b931 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 e70f5d3a..1fd7c589 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 9b1be9c9..4e681b97 100644
--- a/server/providers/krb5/krb5_child.c
+++ b/server/providers/krb5/krb5_child.c
@@ -25,6 +25,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
+#include <popt.h>
#include <security/pam_modules.h>
@@ -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 c6aa27c9..862367ce 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 b7deb854..a9d25532 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 */