diff options
-rw-r--r-- | server/Makefile.in | 19 | ||||
-rw-r--r-- | server/confdb/confdb.c | 314 | ||||
-rw-r--r-- | server/confdb/confdb.h | 12 | ||||
-rw-r--r-- | server/confdb/confdb_private.h | 42 | ||||
-rw-r--r-- | server/configure.ac | 2 | ||||
-rw-r--r-- | server/examples/config.ldif | 88 | ||||
-rw-r--r-- | server/examples/db.ldif | 71 | ||||
-rw-r--r-- | server/examples/sssd.conf | 51 | ||||
-rw-r--r-- | server/monitor/monitor.c | 353 | ||||
-rw-r--r-- | server/monitor/monitor.h | 7 | ||||
-rw-r--r-- | server/sbus/sssd_dbus_connection.c | 1 |
11 files changed, 686 insertions, 274 deletions
diff --git a/server/Makefile.in b/server/Makefile.in index d7d114c3..8aabd2f0 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -18,6 +18,7 @@ builddir = @builddir@ sharedbuilddir = @sharedbuilddir@ INSTALLCMD = @INSTALL@ EXTRA_OBJ=@EXTRA_OBJ@ +SSSD_CONF_DIR = @sysconfdir@/sssd SSSD_LIBEXEC_PATH = @libexecdir@/@PACKAGE_NAME@ SSSD_LIBDIR = @pluginpath@ LDB_LIBDIR = @libdir@/ldb @@ -62,6 +63,12 @@ OPENLDAP_LIBS = @OPENLDAP_LIBS@ LDAP_CFLAGS = $(OPENLDAP_CFLAGS) LDAP_LIBS = $(OPENLDAP_LIBS) +COLLECTION_CFLAGS = -I ../common/collection -I../common/trace +COLLECTION_LIBS = -L ../common/collection/.libs/ -lcollection + +INI_CFG_CFLAGS = -I ../common/ini +INI_CFG_LIBS = -L ../common/ini/.libs/ -lini_config + LIBDL = @LIBDL@ SHLIBEXT = @SHLIBEXT@ @@ -72,13 +79,15 @@ SHLD_FLAGS = @SHLD_FLAGS@ SONAMEFLAG = @SONAMEFLAG@ LDFLAGS += @LDFLAGS@ -L$(srcdir)/lib -LIBS = @LIBS@ $(TALLOC_LIBS) $(TDB_LIBS) $(TEVENT_LIBS) $(POPT_LIBS) $(LDB_LIBS) $(DBUS_LIBS) $(PCRE_LIBS) +LIBS = @LIBS@ $(TALLOC_LIBS) $(TDB_LIBS) $(TEVENT_LIBS) $(POPT_LIBS) $(LDB_LIBS) $(DBUS_LIBS) $(PCRE_LIBS) $(INI_CFG_LIBS) $(COLLECTION_LIBS) PICFLAG = @PICFLAG@ CFLAGS := -I$(srcdir)/include -Iinclude -I$(srcdir) -I$(srcdir)/.. \ - $(POPT_CFLAGS) $(TALLOC_CFLAGS) $(TDB_CFLAGS) $(TEVENT_CFLAGS) $(LDB_CFLAGS) $(DBUS_CFLAGS) $(CHECK_CFLAGS) $(PCRE_CFLAGS) \ + $(POPT_CFLAGS) $(TALLOC_CFLAGS) $(TDB_CFLAGS) $(TEVENT_CFLAGS) \ + $(LDB_CFLAGS) $(DBUS_CFLAGS) $(CHECK_CFLAGS) $(PCRE_CFLAGS) \ + $(COLLECTION_CFLAGS) $(INI_CFG_CFLAGS)\ -DLIBDIR=\"$(libdir)\" -DVARDIR=\"$(localstatedir)\" -DSHLIBEXT=\"$(SHLIBEXT)\" -DSSSD_LIBEXEC_PATH=\"$(SSSD_LIBEXEC_PATH)\" \ - -DSSSD_INTROSPECT_PATH=\"$(SSSD_INTROSPECT_PATH)\" -DUSE_MMAP=1 $(CFLAGS) + -DSSSD_INTROSPECT_PATH=\"$(SSSD_INTROSPECT_PATH)\" -DSSSD_CONF_DIR=\"$(SSSD_CONF_DIR)\" -DUSE_MMAP=1 $(CFLAGS) MDLD = @MDLD@ MDLD_FLAGS = @MDLD_FLAGS@ @@ -109,6 +118,7 @@ OBJS = $(SERVER_OBJ) $(EXTRA_OBJ) headers = DBUS_SYSBUS_POLICY_DIR = @sysconfdir@/dbus-1/system.d +SSSD_CONF_FILE = etc/sssd.conf LIBEXECBINS = sbin/sssd_nss sbin/sssd_dp sbin/sssd_be sbin/sssd_pam ifneq (x$(HAVE_INFOPIPE), x) @@ -180,7 +190,8 @@ installdirs:: $(DESTDIR)$(SSSD_INTROSPECT_PATH)/infopipe \ $(DESTDIR)$(SSSD_PIPE_PATH)/private \ $(DESTDIR)$(SSSD_DB_PATH) \ - $(DESTDIR)$(SSSD_PID_PATH) + $(DESTDIR)$(SSSD_PID_PATH) \ + $(DESTDIR)$(SSSD_CONF_DIR) installheaders:: installdirs ifneq (x$(headers), x) diff --git a/server/confdb/confdb.c b/server/confdb/confdb.c index 88700e30..4256418a 100644 --- a/server/confdb/confdb.c +++ b/server/confdb/confdb.c @@ -20,6 +20,10 @@ */ #define _GNU_SOURCE + +#include "talloc.h" +#include "tevent.h" +#include "config.h" #include "ldb.h" #include "ldb_errors.h" #include "util/util.h" @@ -27,8 +31,13 @@ #include "confdb/confdb_private.h" #include "util/btreemap.h" #include "db/sysdb.h" -#define CONFDB_VERSION "0.1" -#define CONFDB_DOMAIN_BASEDN "cn=domains,cn=config" +#include "collection.h" +#include "collection_tools.h" +#include "ini_config.h" + +#define CONFDB_VERSION "1" +#define CONFDB_BASEDN "cn=config" +#define CONFDB_DOMAIN_BASEDN "cn=domains,"CONFDB_BASEDN #define CONFDB_DOMAIN_ATTR "cn" #define CONFDB_MPG "magicPrivateGroups" #define CONFDB_FQ "useFullyQualifiedNames" @@ -487,7 +496,7 @@ failed: return ret; } -static int confdb_test(struct confdb_ctx *cdb) +int confdb_test(struct confdb_ctx *cdb) { char **values; int ret; @@ -522,23 +531,254 @@ static int confdb_test(struct confdb_ctx *cdb) return EOK; } -static int confdb_init_db(struct confdb_ctx *cdb) +static int confdb_purge(struct confdb_ctx *cdb) +{ + int ret, i; + TALLOC_CTX *tmp_ctx; + struct ldb_result *res; + struct ldb_dn *dn; + const char *attrs[] = { "dn", NULL }; + + tmp_ctx = talloc_new(NULL); + + dn = ldb_dn_new(tmp_ctx, cdb->ldb, "cn=config"); + + /* Get the list of all DNs */ + ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, + LDB_SCOPE_SUBTREE, attrs, NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + for(i=0; i<res->count; i++) { + /* Delete this DN */ + ret = ldb_delete(cdb->ldb, res->msgs[i]->dn); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + } + +done: + talloc_free(tmp_ctx); + return ret; +} + +int confdb_create_base(struct confdb_ctx *cdb) { - const char *base_ldif; - struct ldb_ldif *ldif; - const char *val[2] = {NULL, NULL}; int ret; + struct ldb_ldif *ldif; + + const char *base_ldif = CONFDB_BASE_LDIF; + + while ((ldif = ldb_ldif_read_string(cdb->ldb, &base_ldif))) { + ret = ldb_add(cdb->ldb, ldif->msg); + if (ret != LDB_SUCCESS) { + DEBUG(0, ("Failed to initialize DB (%d,[%s]), aborting!\n", + ret, ldb_errstring(cdb->ldb))); + return EIO; + } + ldb_ldif_read_free(cdb->ldb, ldif); + } + + return EOK; +} + +static int confdb_create_ldif(TALLOC_CTX *mem_ctx, + struct collection_item *sssd_config, + char **config_ldif) +{ + int ret, i, j; + char *ldif; + char *tmp_ldif; + char *writer; + char **sections; + int section_count; + char *dn; + char *tmp_dn; + char *sec_dn; + char **attrs; + int attr_count; + char *ldif_attr; + struct collection_item *attr; + TALLOC_CTX *tmp_ctx; + size_t dn_size; + size_t ldif_len; + size_t attr_len; + + ldif_len = strlen(CONFDB_INTERNAL_LDIF); + ldif = talloc_array(mem_ctx, char, ldif_len+1); + if (!ldif) return ENOMEM; + + tmp_ctx = talloc_new(ldif); + if (!tmp_ctx) { + ret = ENOMEM; + goto error; + } + + memcpy(ldif, CONFDB_INTERNAL_LDIF, ldif_len); + writer = ldif+ldif_len; + + /* Read in the collection and convert it to an LDIF */ + /* Get the list of sections */ + sections = get_section_list(sssd_config, §ion_count, &ret); + if (ret != EOK) { + goto error; + } + + for(i = 0; i < section_count; i++) { + const char *rdn = NULL; + DEBUG(6,("Processing config section [%s]\n", sections[i])); + ret = parse_section(tmp_ctx, sections[i], &sec_dn, &rdn); + if (ret != EOK) { + goto error; + } + + dn = talloc_asprintf(tmp_ctx, + "dn: %s,cn=config\n" + "cn: %s\n", + sec_dn, rdn); + if(!dn) { + ret = ENOMEM; + free_section_list(sections); + goto error; + } + dn_size = strlen(dn); + + /* Get all of the attributes and their values as LDIF */ + attrs = get_attribute_list(sssd_config, sections[i], + &attr_count, &ret); + if (ret != EOK) { + free_section_list(sections); + goto error; + } + + for(j = 0; j < attr_count; j++) { + DEBUG(6, ("Processing attribute [%s]\n", attrs[j])); + ret = get_config_item(sections[i], attrs[j], sssd_config, + &attr); + if (ret != EOK) goto error; + + const char *value = get_const_string_config_value(attr, &ret); + if (ret != EOK) goto error; + + ldif_attr = talloc_asprintf(tmp_ctx, + "%s: %s\n", attrs[j], value); + DEBUG(9, ("%s", ldif_attr)); + + attr_len = strlen(ldif_attr); + + tmp_dn = talloc_realloc(tmp_ctx, dn, char, + dn_size+attr_len+1); + if(!tmp_dn) { + ret = ENOMEM; + free_attribute_list(attrs); + free_section_list(sections); + goto error; + } + dn = tmp_dn; + memcpy(dn+dn_size, ldif_attr, attr_len+1); + dn_size += attr_len; + } + + dn_size ++; + tmp_dn = talloc_realloc(tmp_ctx, dn, char, + dn_size+1); + if(!tmp_dn) { + ret = ENOMEM; + free_attribute_list(attrs); + free_section_list(sections); + goto error; + } + dn = tmp_dn; + dn[dn_size-1] = '\n'; + dn[dn_size] = '\0'; + + DEBUG(9, ("Section dn\n%s", dn)); + + tmp_ldif = talloc_realloc(mem_ctx, ldif, char, + ldif_len+dn_size+1); + if(!tmp_ldif) { + ret = ENOMEM; + free_attribute_list(attrs); + free_section_list(sections); + goto error; + } + ldif = tmp_ldif; + memcpy(ldif+ldif_len, dn, dn_size); + ldif_len += dn_size; + + free_attribute_list(attrs); + talloc_free(dn); + } + + ldif[ldif_len] = '\0'; + + free_section_list(sections); + + *config_ldif = ldif; + talloc_free(tmp_ctx); + return EOK; + +error: + talloc_free(ldif); + return ret; +} + +int confdb_init_db(const char *config_file, struct confdb_ctx *cdb) +{ + int ret, i; + struct collection_item *sssd_config = NULL; + struct collection_item *error_list = NULL; + char *config_ldif; + struct ldb_ldif *ldif; TALLOC_CTX *tmp_ctx; tmp_ctx = talloc_new(cdb); if(tmp_ctx == NULL) return ENOMEM; - /* cn=confdb does not exists, means db is empty, populate */ - base_ldif = CONFDB_BASE_LDIF; - while ((ldif = ldb_ldif_read_string(cdb->ldb, &base_ldif))) { + /* Set up a transaction to replace the configuration */ + ret = ldb_transaction_start(cdb->ldb); + if (ret != LDB_SUCCESS) { + DEBUG(0, ("Failed to start a transaction for updating the configuration\n")); + talloc_free(tmp_ctx); + return sysdb_error_to_errno(ret); + } + + /* Purge existing database */ + ret = confdb_purge(cdb); + if (ret != EOK) { + DEBUG(0, ("Could not purge existing configuration\n")); + goto done; + } + + /* Read the configuration into a collection */ + ret = config_from_file("sssd", config_file, &sssd_config, + INI_STOP_ON_ANY, &error_list); + if (ret != EOK) { + DEBUG(0, ("Parse error reading configuration file [%s]\n", + config_file)); + print_file_parsing_errors(stderr, error_list); + destroy_collection(error_list); + destroy_collection(sssd_config); + goto done; + } + + ret = confdb_create_ldif(tmp_ctx, sssd_config, &config_ldif); + destroy_collection(sssd_config); + if (ret != EOK) { + DEBUG(0, ("Could not create LDIF for confdb\n")); + goto done; + } + + DEBUG(7, ("LDIF file to import: \n%s", config_ldif)); + + i=0; + while ((ldif = ldb_ldif_read_string(cdb->ldb, (const char **)&config_ldif))) { ret = ldb_add(cdb->ldb, ldif->msg); if (ret != LDB_SUCCESS) { - DEBUG(0, ("Failed to inizialiaze DB (%d,[%s]), aborting!\n", + DEBUG(0, ("Failed to initialize DB (%d,[%s]), aborting!\n", ret, ldb_errstring(cdb->ldb))); ret = EIO; goto done; @@ -546,45 +786,12 @@ static int confdb_init_db(struct confdb_ctx *cdb) ldb_ldif_read_free(cdb->ldb, ldif); } -/* InfoPipe */ -#ifdef HAVE_INFOPIPE - /* Set the sssd_info description */ - val[0] = "InfoPipe Configuration"; - ret = confdb_add_param(cdb, false, "config/services/info", "description", val); - if (ret != EOK) goto done; - - /* Set the sssd_info command path */ - val[0] = talloc_asprintf(tmp_ctx, "%s/sssd_info", SSSD_LIBEXEC_PATH); - CONFDB_ZERO_CHECK_OR_JUMP(val[0], ret, ENOMEM, done); - ret = confdb_add_param(cdb, false, "config/services/info", "command", val); - if (ret != EOK) goto done; - - /* Add the InfoPipe to the list of active services */ - val[0] = "info"; - ret = confdb_add_param(cdb, false, "config/services", "activeServices", val); - if (ret != EOK) goto done; -#endif - -/* PolicyKit */ -#ifdef HAVE_POLICYKIT - /* Set the sssd_pk description */ - val[0] = "PolicyKit Backend Configuration"; - ret = confdb_add_param(cdb, false, "config/services/pk", "description", val); - if (ret != EOK) goto done; - - /* Set the sssd_info command path */ - val[0] = talloc_asprintf(tmp_ctx, "%s/sssd_pk", SSSD_LIBEXEC_PATH); - CONFDB_ZERO_CHECK_OR_JUMP(val[0], ret, ENOMEM, done); - ret = confdb_add_param(cdb, false, "config/services/pk", "command", val); - if (ret != EOK) goto done; - - /* Add the InfoPipe to the list of active services */ - val[0] = "pk"; - ret = confdb_add_param(cdb, false, "config/services", "activeServices", val); - if (ret != EOK) goto done; -#endif + ret = EOK; done: + ret == EOK ? + ldb_transaction_commit(cdb->ldb) : + ldb_transaction_cancel(cdb->ldb); talloc_free(tmp_ctx); return ret; } @@ -595,7 +802,7 @@ int confdb_init(TALLOC_CTX *mem_ctx, char *confdb_location) { struct confdb_ctx *cdb; - int ret; + int ret = EOK; cdb = talloc_zero(mem_ctx, struct confdb_ctx); if (!cdb) @@ -626,15 +833,6 @@ int confdb_init(TALLOC_CTX *mem_ctx, return EIO; } - ret = confdb_test(cdb); - if (ret == ENOENT) { - ret = confdb_init_db(cdb); - } - if (ret != EOK) { - talloc_free(cdb); - return ret; - } - *cdb_ctx = cdb; return EOK; diff --git a/server/confdb/confdb.h b/server/confdb/confdb.h index b366d60d..ae66807a 100644 --- a/server/confdb/confdb.h +++ b/server/confdb/confdb.h @@ -26,10 +26,16 @@ #include "talloc.h" #include "tevent.h" #include "util/btreemap.h" +#include "config.h" #define CONFDB_FILE "config.ldb" +#define CONFDB_DEFAULT_CONFIG_FILE SSSD_CONF_DIR"/sssd.conf" #define SSSD_MIN_ID 1000 +struct confdb_ctx; + +typedef int (*confdb_reconf_fn) (struct confdb_ctx *cdb, void *pvt); + struct sss_domain_info { char *name; char *provider; @@ -44,8 +50,6 @@ struct sss_domain_info { struct sss_domain_info *next; }; -struct confdb_ctx; - int confdb_add_param(struct confdb_ctx *cdb, bool replace, const char *section, @@ -80,4 +84,8 @@ int confdb_get_domains(struct confdb_ctx *cdb, TALLOC_CTX *mem_ctx, struct sss_domain_info **domains); +int confdb_create_base(struct confdb_ctx *cdb); +int confdb_test(struct confdb_ctx *cdb); +int confdb_init_db(const char *config_file, struct confdb_ctx *cdb); + #endif diff --git a/server/confdb/confdb_private.h b/server/confdb/confdb_private.h index c632f97d..f3791953 100644 --- a/server/confdb/confdb_private.h +++ b/server/confdb/confdb_private.h @@ -12,43 +12,9 @@ "\n" \ "dn: @MODULES\n" \ "@LIST: server_sort\n" \ - "\n" \ + "\n" + +#define CONFDB_INTERNAL_LDIF \ "dn: cn=config\n" \ - "cn: config\n" \ - "version: 0.1\n" \ - "description: base object\n" \ - "\n" \ - "dn: cn=services,cn=config\n" \ - "cn: services\n" \ - "description: Local service configuration\n" \ - "activeServices: dp\n" \ - "activeServices: nss\n" \ - "activeServices: pam\n" \ - "\n" \ - "dn: cn=monitor,cn=services,cn=config\n" \ - "cn: monitor\n" \ - "description: Monitor Configuration\n" \ - "\n" \ - "dn: cn=dp,cn=services,cn=config\n" \ - "cn: dp\n" \ - "description: Data Provider Configuration\n" \ - "\n" \ - "dn: cn=nss,cn=services,cn=config\n" \ - "cn: nss\n" \ - "description: NSS Responder Configuration\n" \ - "\n" \ - "dn: cn=pam,cn=services,cn=config\n" \ - "cn: pam\n" \ - "description: PAM Responder Configuration\n" \ - "\n" \ - "dn: cn=domains,cn=config\n" \ - "cn: domains\n" \ - "description: Domains served by SSSD\n" \ - "domains: LOCAL\n" \ - "\n" \ - "dn: cn=LOCAL,cn=domains,cn=config\n" \ - "cn: LOCAL\n" \ - "description: LOCAL domain\n" \ - "enumerate: 3\n" \ - "magicPrivateGroups: TRUE\n" \ + "version: 1\n" \ "\n" diff --git a/server/configure.ac b/server/configure.ac index b3738802..fade762d 100644 --- a/server/configure.ac +++ b/server/configure.ac @@ -76,4 +76,6 @@ AC_LIBREPLACE_MDLD AC_LIBREPLACE_MDLD_FLAGS AC_LIBREPLACE_RUNTIME_LIB_PATH_VAR +AC_CHECK_HEADERS([sys/inotify.h]) + AC_OUTPUT(Makefile) diff --git a/server/examples/config.ldif b/server/examples/config.ldif deleted file mode 100644 index b9eb3340..00000000 --- a/server/examples/config.ldif +++ /dev/null @@ -1,88 +0,0 @@ -# editing 4 records -# record 1 -dn: cn=config -cn: config -version: 0.1 - -dn: cn=services,cn=config -cn: services -description: Local service configuration -activeServices: nss -activeServices: dp -activeServices: pam -activeServices: info - -dn: cn=nss,cn=services,cn=config -cn: nss -description: NSS Responder Configuration -filterGroups: root -filterGroups: foo@TEST -filterUsers: root -filterUsers: bar@TEST - -dn: cn=dp,cn=services,cn=config -cn: dp -description: Data Provider Configuration - -dn: cn=monitor,cn=services,cn=config -cn: monitor -description: Monitor Configuration -sbusTimeout: 10 -servicePingTime: 10 - -dn: cn=pam,cn=services,cn=config -cn: pam -description: PAM Responder Configuration - -dn: cn=info,cn=services,cn=config -cn: info -description: InfoPipe Configuration - -dn: cn=domains,cn=config -cn: domains -description: Domains served by SSSD -domains: LOCAL, EXAMPLE.COM, TEST - -dn: cn=LOCAL,cn=domains,cn=config -cn: LOCAL -description: Reserved domain for local configurations -enumerate: 3 -minId: 500 -maxId: 999 -legacy: TRUE -libName: files -libPath: /lib64/libnss_files.so.2 -magicPrivateGroups: FALSE -provider: proxy -auth-module: proxy -pam-target: sssdproxylocal - -dn: cn=TEST,cn=domains,cn=config -cn: TEST -description: TEST Ldap domain -libName: ldap -libPath: /usr/lib64/libnss_ldap.so.2 -legacy: TRUE -enumerate: 3 -useFullyQualifiedNames: TRUE -minId: 1000 -provider: proxy -auth-module: proxy -pam-target: sssdproxytest - -dn: cn=LDAPTEST,cn=domains,cn=config -cn: LDAPTEST -basedn: cn=LDAPTEST,sn=sysdb -command: /usr/libexec/sssd/sssd_be --provider ldap --domain LDAPTEST -description: TEST PAM Ldap domain -provider: ldap -userSearchBase: ou=user,dc=my-domain,dc=com - -dn: cn=EXAMPLE.COM,cn=domains,cn=config -cn: EXAMPLE.COM -description: Example domain served by IPA -provider: ipa -server: ipaserver1.example.com -server: ipabackupserver.example.com -legacy: FALSE -enumerate: 0 diff --git a/server/examples/db.ldif b/server/examples/db.ldif deleted file mode 100644 index 9ded6c79..00000000 --- a/server/examples/db.ldif +++ /dev/null @@ -1,71 +0,0 @@ -dn: @ATTRIBUTES -userPrincipalName: CASE_INSENSITIVE -cn: CASE_INSENSITIVE -dc: CASE_INSENSITIVE -dn: CASE_INSENSITIVE -name: CASE_INSENSITIVE -objectclass: CASE_INSENSITIVE - -dn: @INDEXLIST -@IDXATTR: cn -@IDXATTR: objectclass -@IDXATTR: member -@IDXATTR: memberof -@IDXATTR: memberUid -@IDXATTR: uid -@IDXATTR: gid -@IDXATTR: uidNumber -@IDXATTR: gidNumber -@IDXATTR: lastUpdate - -dn: @MODULES -@LIST: asq,memberof - -dn: cn=sysdb -cn: sysdb -version: 0.1 -description: base object - -dn: cn=local,cn=sysdb -cn: local -description: Local system data - -dn: cn=groups,cn=local,cn=sysdb -cn: groups -description: Local POSIX groups - -dn: gid=foousers,cn=groups,cn=local,cn=sysdb -gid: foousers -description: Local user accounts -member: uid=foobar,cn=users,cn=local,cn=sysdb -objectclass: group -gidNumber: 10101 - -dn: cn=users,cn=local,cn=sysdb -cn: users -description: Local POSIX users - -dn: uid=foobar,cn=users,cn=local,cn=sysdb -uid: foobar -objectClass: user -description: User Foo Bar -uidNumber: 10101 -gidNumber: 10101 -legacy: false -primaryGroup: cn=foousers,cn=groups,cn=local,cn=sysdb -userPassword: !@#$%#@#@!FOOBAR -homeDirectory: /home/foobar -fullName: Foo Bar -loginShell: /bin/bash -accountExpires: 20500101000000Z -biometricSignature: <binary> -disabled: false -failedLoginAttempts: 0 -keyboardLayout: it_IT -lastPasswordChange: 20080912142034Z -passwordHint: Favorite pasta sauce -passwordHistory: foo,bar,baz -preferredLanguage: IT -preferredSession: GNOME -memberOf: cn=foousers,cn=groups,cn=local,cn=sysdb - diff --git a/server/examples/sssd.conf b/server/examples/sssd.conf new file mode 100644 index 00000000..b15e92ff --- /dev/null +++ b/server/examples/sssd.conf @@ -0,0 +1,51 @@ +[services] +description = Local Service Configuration +activeServices = nss, dp, pam, info + +[services/nss] +description = NSS Responder Configuration +timeout = 10 +filterGroups = root, foo@TEST +filterUsers = root, bar@TEST + +[services/dp] +description = Data Provider Configuration +timeout = 10 + +[services/pam] +description = PAM Responder Configuration +timeout = 10 + +[services/info] +description = InfoPipe Configuration +timeout = 10 + +[services/monitor] +description = Service Monitor Configuration +sbusTimeout = 10 +servicePingTime = 10 + +[domains] +description = Domains served by SSSD +domains = LOCAL + +[domains/LOCAL] +description = Reserved domain for local configurations +enumerate = 3 +minId = 500 +maxId = 999 +legacy = TRUE +libName = files +libPath = /lib64/libnss_files.so.2 +magicPrivateGroups = FALSE +provider = proxy +auth-module = proxy +pam-target = sssdproxylocal + +[domains/EXAMPLE.COM] +description = Example LDAP domain +basedn = dc=example,dc=com +command = /usr/libexec/sssd/sssd_be --provider ldap --domain EXAMPLE.COM +provider = ldap +userSearchBase = ou=user,dc=example,dc=com + diff --git a/server/monitor/monitor.c b/server/monitor/monitor.c index 65664ca6..16811224 100644 --- a/server/monitor/monitor.c +++ b/server/monitor/monitor.c @@ -24,6 +24,14 @@ #include <sys/wait.h> #include <sys/time.h> #include <time.h> +#include "config.h" +#ifdef HAVE_SYS_INOTIFY_H +#include <sys/inotify.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> #include "util/util.h" #include "popt.h" #include "tevent.h" @@ -79,6 +87,17 @@ struct mt_ctx { int service_id_timeout; }; +struct config_file_ctx { + TALLOC_CTX *parent_ctx; + struct confdb_ctx *cdb; + struct tevent_context *ev; + int fd; + char *filename; + time_t modified; + confdb_reconf_fn reconf_fn; + void *reconf_pvt; +}; + static int start_service(struct mt_svc *mt_svc); static int dbus_service_init(struct sbus_conn_ctx *conn_ctx, void *data); @@ -97,8 +116,11 @@ static int get_service_config(struct mt_ctx *ctx, const char *name, struct mt_svc **svc_cfg); static int get_provider_config(struct mt_ctx *ctx, const char *name, struct mt_svc **svc_cfg); -static int add_new_service (struct mt_ctx *ctx, const char *name); -static int add_new_provider (struct mt_ctx *ctx, const char *name); +static int add_new_service(struct mt_ctx *ctx, const char *name); +static int add_new_provider(struct mt_ctx *ctx, const char *name); + +static int monitor_signal_reconf(struct confdb_ctx *cdb, void *pvt); +static int update_monitor_config(struct mt_ctx *ctx); /* dbus_get_monitor_version * Return the monitor version over D-BUS */ @@ -474,6 +496,13 @@ done: dbus_message_unref(reply); } +static int monitor_signal_reconf(struct confdb_ctx *cdb, void *pvt) +{ + struct mt_ctx *ctx = talloc_get_type(pvt, struct mt_ctx); + DEBUG(1, ("Configuration has changed. Reloading.\n")); + return update_monitor_config(ctx); +} + static int service_signal_reload(struct mt_svc *svc) { DBusMessage *msg; @@ -513,6 +542,11 @@ static int service_signal_reload(struct mt_svc *svc) int get_monitor_config(struct mt_ctx *ctx) { int ret; + size_t svc_count = 0; + char *svcs; + char *cur, *p, *t; + char **svc_list = NULL; + char **tmp_list = NULL; ret = confdb_get_int(ctx->cdb, ctx, MONITOR_CONF_ENTRY, "sbusTimeout", @@ -521,22 +555,61 @@ int get_monitor_config(struct mt_ctx *ctx) return ret; } - ret = confdb_get_param(ctx->cdb, ctx, - "config/services", "activeServices", - &ctx->services); + ret = confdb_get_string(ctx->cdb, ctx, + "config/services", "activeServices", + NULL, &svcs); - if (ctx->services[0] == NULL) { + if (ret != EOK || svcs == NULL) { DEBUG(0, ("No services configured!\n")); return EINVAL; } + cur = p = talloc_strdup(svcs, svcs); + while (p && *p) { + for (cur = p; (*cur == ' ' || *cur == '\t'); cur++) /* trim */ ; + if (!*cur) break; + + p = strchr(cur, ','); + if (p) { + /* terminate element */ + *p = '\0'; + /* trim spaces */ + for (t = p-1; (*t == ' ' || *t == '\t'); t--) *t = '\0'; + p++; + } + + svc_count++; + tmp_list = talloc_realloc(svcs, svc_list, char *, svc_count); + if (!tmp_list) { + ret = ENOMEM; + goto done; + } + svc_list = tmp_list; + svc_list[svc_count-1] = talloc_strdup(svc_list, cur); + } + + svc_count++; + tmp_list = talloc_realloc(svcs, svc_list, char *, svc_count); + if (!tmp_list) { + ret = ENOMEM; + goto done; + } + svc_list = tmp_list; + svc_list[svc_count-1] = NULL; + + ctx->services = talloc_steal(ctx, svc_list); + ret = confdb_get_domains(ctx->cdb, ctx, &ctx->domains); if (ret != EOK) { DEBUG(2, ("No domains configured. LOCAL should always exist!\n")); return ret; } - return EOK; + ret = EOK; + +done: + talloc_free(svcs); + return ret; } static int get_service_config(struct mt_ctx *ctx, const char *name, @@ -604,7 +677,7 @@ static int get_service_config(struct mt_ctx *ctx, const char *name, return EOK; } -static int add_new_service (struct mt_ctx *ctx, const char *name) +static int add_new_service(struct mt_ctx *ctx, const char *name) { int ret; struct mt_svc *svc; @@ -701,7 +774,7 @@ static int get_provider_config(struct mt_ctx *ctx, const char *name, return EOK; } -static int add_new_provider (struct mt_ctx *ctx, const char *name) +static int add_new_provider(struct mt_ctx *ctx, const char *name) { int ret; struct mt_svc *svc; @@ -958,9 +1031,233 @@ static void monitor_hup(struct tevent_context *ev, update_monitor_config(ctx); } +#ifdef HAVE_SYS_INOTIFY_H +static void config_file_changed(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *data) +{ + int ret; + TALLOC_CTX *tmp_ctx; + struct inotify_event *in_event; + char *buf; + char *name; + ssize_t len, total_len; + ssize_t event_size = sizeof(struct inotify_event); + struct config_file_ctx *file_ctx = + talloc_get_type(data, struct config_file_ctx); + + DEBUG(1, ("Config file changed\n")); + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) return; + + buf = talloc_size(tmp_ctx, event_size); + if (!buf) { + talloc_free(tmp_ctx); + return; + } + + total_len = 0; + while (total_len < event_size) { + len = read(file_ctx->fd, &buf+total_len, event_size-total_len); + if (len == -1 && errno != EINTR) { + DEBUG(0, ("Critical error reading inotify file descriptor.\n")); + talloc_free(tmp_ctx); + return; + } + total_len += len; + } + + in_event = (struct inotify_event *)&buf; + + if (in_event->len > 0) { + /* Read in the name, even though we don't use it, + * so that read ptr is in the right place + */ + name = talloc_size(tmp_ctx, len); + total_len = 0; + while (total_len < in_event->len) { + len = read(file_ctx->fd, &name, in_event->len); + if (len == -1 && errno != EINTR) { + DEBUG(0, ("Critical error reading inotify file descriptor.\n")); + talloc_free(tmp_ctx); + return; + } + total_len += len; + } + } + + /* Parse the configuration file */ + ret = confdb_init_db(file_ctx->filename, file_ctx->cdb); + if (ret != EOK) { + DEBUG(0, ("Could not reload configuration!")); + kill(getpid(), SIGTERM); + } + + /* Tell the monitor to signal the children */ + file_ctx->reconf_fn(file_ctx->cdb, file_ctx->reconf_pvt); + + talloc_free(tmp_ctx); +} +#endif + +static void poll_config_file(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval t, void *ptr) +{ + int ret, err; + struct stat file_stat; + struct timeval tv; + struct tevent_timer *timer; + struct config_file_ctx *file_ctx = + talloc_get_type(ptr,struct config_file_ctx); + + ret = stat(file_ctx->filename, &file_stat); + if (ret < 0) { + err = errno; + DEBUG(0, ("Could not stat file [%s]. Error [%d:%s]\n", + file_ctx->filename, err, strerror(err))); + /* TODO: If the config file is missing, should we shut down? */ + return; + } + + if (file_stat.st_mtime != file_ctx->modified) { + /* Parse the configuration file and signal the children */ + /* Note: this will fire if the modification time changes into the past + * as well as the future. + */ + DEBUG(1, ("Config file changed\n")); + file_ctx->modified = file_stat.st_mtime; + + ret = confdb_init_db(file_ctx->filename, file_ctx->cdb); + if (ret != EOK) { + DEBUG(0, ("Could not reload configuration!")); + kill(getpid(), SIGTERM); + } + + /* Tell the monitor to signal the children */ + file_ctx->reconf_fn(file_ctx->cdb, file_ctx->reconf_pvt); + } + + gettimeofday(&tv, NULL); + tv.tv_sec += CONFIG_FILE_POLL_INTERVAL; + tv.tv_usec = 0; + timer = tevent_add_timer(ev, file_ctx->parent_ctx, tv, + poll_config_file, file_ctx); + if (!timer) { + DEBUG(0, ("Error: Config file no longer monitored for changes!")); + } +} + +static int try_inotify(struct config_file_ctx *file_ctx) +{ +#ifdef HAVE_SYS_INOTIFY_H + int fd, wd, err, fd_args, ret; + struct tevent_fd *tfd; + + /* Set up inotify to monitor the config file for changes */ + fd = inotify_init(); + if (fd < 0) { + err = errno; + DEBUG(0, ("Could not initialize inotify, error [%d:%s]\n", + err, strerror(err))); + return err; + } + + fd_args = fcntl(fd, F_GETFL, NULL); + if (fd_args < 0) { + /* Could not set nonblocking */ + close(fd); + return EINVAL; + } + + fd_args |= O_NONBLOCK; + ret = fcntl(fd, F_SETFL, fd_args); + if (ret < 0) { + /* Could not set nonblocking */ + close(fd); + return EINVAL; + } + + wd = inotify_add_watch(fd, file_ctx->filename, IN_MODIFY); + if (wd < 0) { + err = errno; + DEBUG(0, ("Could not add inotify watch for file [%s]. Error [%d:%s]\n", + file_ctx->filename, err, strerror(err))); + close(fd); + return err; + } + + /* Add the inotify file descriptor to the TEvent context */ + file_ctx->fd = fd; + + tfd = tevent_add_fd(file_ctx->ev, file_ctx, fd, TEVENT_FD_READ, + config_file_changed, file_ctx); + if (!tfd) { + inotify_rm_watch(fd, wd); + close(fd); + return EIO; + } + return EOK; +#else + return EINVAL; +#endif +} + +static int monitor_config_file(TALLOC_CTX *mem_ctx, + struct confdb_ctx *cdb, + struct tevent_context *ev, + const char *file, + confdb_reconf_fn fn, + void *reconf_pvt) +{ + int ret, err; + struct timeval tv; + + struct stat file_stat; + struct config_file_ctx *file_ctx; + + struct tevent_timer *timer; + + ret = stat(file, &file_stat); + if (ret < 0) { + err = errno; + DEBUG(0, ("Could not stat file [%s]. Error [%d:%s]\n", + file, err, strerror(err))); + return err; + } + + file_ctx = talloc_zero(mem_ctx, struct config_file_ctx); + if (!file_ctx) return ENOMEM; + + file_ctx->parent_ctx = mem_ctx; + file_ctx->cdb = cdb; + file_ctx->filename = talloc_strdup(file_ctx, file); + file_ctx->modified = file_stat.st_mtime; + file_ctx->reconf_fn = fn; + file_ctx->reconf_pvt = reconf_pvt; + file_ctx->ev = ev; + + ret = try_inotify(file_ctx); + if (ret != EOK) { + /* Could not monitor file with inotify, fall back to polling */ + gettimeofday(&tv, NULL); + tv.tv_sec += CONFIG_FILE_POLL_INTERVAL; + tv.tv_usec = 0; + timer = tevent_add_timer(ev, mem_ctx, tv, poll_config_file, file_ctx); + if (!timer) { + talloc_free(file_ctx); + return EIO; + } + } + + return EOK; +} + int monitor_process_init(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx, - struct confdb_ctx *cdb) + struct confdb_ctx *cdb, + const char *config_file) { struct mt_ctx *ctx; struct sysdb_ctx *sysdb; @@ -976,10 +1273,37 @@ int monitor_process_init(TALLOC_CTX *mem_ctx, ctx->ev = event_ctx; ctx->cdb = cdb; + /* Initialize the CDB from the configuration file */ + ret = confdb_test(ctx->cdb); + if (ret == ENOENT) { + /* First-time setup + * Load special entries + */ + ret = confdb_create_base(cdb); + if (ret != EOK) { + talloc_free(ctx); + return ret; + } + } + + ret = confdb_init_db(config_file, cdb); + if (ret != EOK) { + talloc_free(cdb); + DEBUG(0, ("ConfDB initialization has failed [%s]\n", + strerror(ret))); + talloc_free(ctx); + return ret; + } + + /* Read in the monitor's configuration */ ret = get_monitor_config(ctx); if (ret != EOK) return ret; + /* Watch for changes to the confdb config file */ + ret = monitor_config_file(ctx, cdb, event_ctx, config_file, monitor_signal_reconf, ctx); + if (ret != EOK) return ret; + /* Avoid a startup race condition between InfoPipe * and NSS. If the sysdb doesn't exist yet, both * will try to create it at the same time. So @@ -1165,6 +1489,8 @@ static void identity_check(DBusPendingCall *pending, void *data) goto done; } + DEBUG(4,("Received ID reply: (%s,%d)\n", svc_name, svc_ver)); + /* search this service in the list */ svc = fake_svc->mt_ctx->svc_list; while (svc) { @@ -1546,6 +1872,7 @@ int main(int argc, const char *argv[]) poptContext pc; int opt_daemon = 0; int opt_interactive = 0; + char *opt_config_file = NULL; int flags = 0; struct main_context *main_ctx; int ret; @@ -1557,6 +1884,8 @@ int main(int argc, const char *argv[]) "Become a daemon (default)", NULL }, \ {"interactive", 'i', POPT_ARG_NONE, &opt_interactive, 0, \ "Run interactive (not a daemon)", NULL}, \ + {"config", 'c', POPT_ARG_STRING, &opt_config_file, 0, \ + "Specify a non-default config file", NULL}, \ { NULL } }; @@ -1581,6 +1910,7 @@ int main(int argc, const char *argv[]) if (opt_daemon) flags |= FLAGS_DAEMON; if (opt_interactive) flags |= FLAGS_INTERACTIVE; + if (!opt_config_file) opt_config_file = CONFDB_DEFAULT_CONFIG_FILE; /* we want a pid file check */ flags |= FLAGS_PID_FILE; @@ -1591,7 +1921,8 @@ int main(int argc, const char *argv[]) ret = monitor_process_init(main_ctx, main_ctx->event_ctx, - main_ctx->confdb_ctx); + main_ctx->confdb_ctx, + opt_config_file); if (ret != EOK) return 3; /* loop on main */ diff --git a/server/monitor/monitor.h b/server/monitor/monitor.h index 77b6e781..2a5218b1 100644 --- a/server/monitor/monitor.h +++ b/server/monitor/monitor.h @@ -1,4 +1,4 @@ -/* +/* SSSD Service monitor @@ -22,8 +22,11 @@ #ifndef _MONITOR_H_ #define _MONITOR_H_ +#define CONFIG_FILE_POLL_INTERVAL 5 /* seconds */ + int monitor_process_init(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx, - struct confdb_ctx *cdb); + struct confdb_ctx *cdb, + const char *config_file); #endif /* _MONITOR_H */ diff --git a/server/sbus/sssd_dbus_connection.c b/server/sbus/sssd_dbus_connection.c index 1a3f107c..cd9d5a18 100644 --- a/server/sbus/sssd_dbus_connection.c +++ b/server/sbus/sssd_dbus_connection.c @@ -573,6 +573,7 @@ DBusHandlerResult sbus_message_handler(DBusConnection *conn, ctx = talloc_get_type(user_data, struct sbus_message_handler_ctx); method = dbus_message_get_member(message); + DEBUG(9, ("Received SBUS method [%s]\n", method)); path = dbus_message_get_path(message); msg_interface = dbus_message_get_interface(message); |