126 struct berval **values;
131 dn = ldap_get_dn(ld, entry);
133 fprintf(stderr,
"sync_touch: Failed getting DN of entry\n");
137 values = ldap_get_values_len(ld, entry,
conf->attr);
139 if (
conf->verbose) printf(
"skipped %s (no %s)\n", dn,
conf->attr);
145 printf(
"would touch %s\n", dn);
146 ldap_value_free_len(values);
152 .mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
154 .mod_bvalues = values
159 ret = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
160 ldap_value_free_len(values);
162 if (ret != LDAP_SUCCESS) {
163 fprintf(stderr,
"sync_touch: Failed touching %s: %s\n", dn, ldap_err2string(ret));
168 if (
conf->verbose) printf(
"touched %s\n", dn);
177 .uri =
"ldap://localhost",
178 .scope = LDAP_SCOPE_SUBTREE,
179 .filter =
"(objectClass=*)"
181 char *pw_from_file = NULL;
184 LDAPMessage *result = NULL, *entry;
186 int c, ret, version = LDAP_VERSION3;
187 int touched = 0, skipped = 0, failed = 0;
188 int status = EXIT_FAILURE;
190 while ((c = getopt(argc, argv,
"b:D:hH:ns:vw:y:Z")) != -1)
switch (c) {
192 conf.base_dn = optarg;
196 conf.bind_dn = optarg;
211 if (strcmp(optarg,
"base") == 0) {
212 conf.scope = LDAP_SCOPE_BASE;
213 }
else if (strcmp(optarg,
"one") == 0) {
214 conf.scope = LDAP_SCOPE_ONELEVEL;
215 }
else if (strcmp(optarg,
"sub") == 0) {
216 conf.scope = LDAP_SCOPE_SUBTREE;
218 fprintf(stderr,
"sync_touch: Invalid scope \"%s\"\n", optarg);
228 conf.bind_pw = optarg;
234 if (!pw_from_file) exit(EXIT_FAILURE);
235 conf.bind_pw = pw_from_file;
239 conf.start_tls =
true;
248 if ((argc < 1) || (argc > 2))
usage(EXIT_FAILURE);
250 if (argc == 2)
conf.filter = argv[1];
253 fprintf(stderr,
"sync_touch: A search base (-b) is required\n");
257 if (
conf.verbose > 1) {
260 if (ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug) != LDAP_OPT_SUCCESS) {
261 fprintf(stderr,
"sync_touch: Failed setting debug level");
266 ret = ldap_initialize(&ld,
conf.uri);
267 if (ret != LDAP_SUCCESS) {
268 fprintf(stderr,
"sync_touch: Failed initialising connection to %s: %s\n",
269 conf.uri, ldap_err2string(ret));
272 if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
273 fprintf(stderr,
"sync_touch: Failed setting protocol version");
277 if (
conf.start_tls) {
278 ret = ldap_start_tls_s(ld, NULL, NULL);
279 if (ret != LDAP_SUCCESS) {
280 fprintf(stderr,
"sync_touch: StartTLS failed: %s\n", ldap_err2string(ret));
285 cred = (
struct berval) {
287 .bv_len =
conf.bind_pw ? strlen(
conf.bind_pw) : 0
289 ret = ldap_sasl_bind_s(ld,
conf.bind_dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
290 if (ret != LDAP_SUCCESS) {
291 fprintf(stderr,
"sync_touch: Bind failed: %s\n", ldap_err2string(ret));
301 ret = ldap_search_ext_s(ld,
conf.base_dn,
conf.scope,
conf.filter, attrs, 0,
302 NULL, NULL, NULL, LDAP_NO_LIMIT, &result);
303 if ((ret != LDAP_SUCCESS) && (ret != LDAP_SIZELIMIT_EXCEEDED)) {
304 fprintf(stderr,
"sync_touch: Search failed: %s\n", ldap_err2string(ret));
307 if (ret == LDAP_SIZELIMIT_EXCEEDED) {
308 fprintf(stderr,
"sync_touch: Server size limit reached, not all matching entries will be touched\n");
311 for (entry = ldap_first_entry(ld, result); entry; entry = ldap_next_entry(ld, entry)) {
327 printf(
"%s %i, skipped %i, failed %i\n",
conf.dry_run ?
"would touch" :
"touched", touched, skipped, failed);
333 if ((failed == 0) && (touched > 0)) status = EXIT_SUCCESS;
336 if (result) ldap_msgfree(result);
337 if (ld) ldap_unbind_ext_s(ld, NULL, NULL);
static int touch_entry(LDAP *ld, sync_touch_conf_t const *conf, LDAPMessage *entry)
Touch one entry by replacing an attribute with the current values of the attribute.