mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-15 03:01:09 +08:00
b5494457d8
This could cause problems on odd systems. The generic headers should be extended as needed to include necessary system headers or, if necessary, make explicit declarations. Extended ac/string.h header to look for string.h/strings.h if STDC_HEADERS is not defined. Also provide basic declarations for str*() functions. This could cause problems on odd systems. Extended ac/unistd.h header to define basic declaration for misc functions that might be missing from headers. This includes externs for getenv(), getopt(), mktemp(), tempname(). Protect fax500.h from multiple inclusion. Moved includes of system/generic headers back to source files. Made mail500 helper functions static. Fixed includes of ctype.h, signal.h, etc. to use generics. lutil/tempname.c: was including stdlib.h twice, one should stdio.h. Wrapped <sys/resource.h> with HAVE_SYS_RESOURCE_H. lber/io.c/ber_get_next(): Changed noctets back to signed. Used with BerRead which expects signed int as second arg and returns signed int.
1236 lines
32 KiB
C
1236 lines
32 KiB
C
/*
|
|
* Copyright (c) 1993, 1994 Regents of the University of Michigan.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms are permitted
|
|
* provided that this notice is preserved and that due credit is given
|
|
* to the University of Michigan at Ann Arbor. The name of the University
|
|
* may not be used to endorse or promote products derived from this
|
|
* software without specific prior written permission. This software
|
|
* is provided ``as is'' without express or implied warranty.
|
|
*
|
|
*/
|
|
|
|
#include "portable.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <ac/string.h>
|
|
#include <ac/ctype.h>
|
|
#include <ac/time.h>
|
|
#include <ac/unistd.h>
|
|
|
|
#include <lber.h>
|
|
#include <ldap.h>
|
|
#include <ldapconfig.h>
|
|
#include "ud.h"
|
|
|
|
static char * bind_and_fetch(char *name);
|
|
|
|
|
|
void
|
|
add_group( char *name )
|
|
{
|
|
register int i, idx = 0, prompt = 0;
|
|
char tmp[BUFSIZ], dn[BUFSIZ];
|
|
static LDAPMod *attrs[9];
|
|
LDAPMod init_rdn, init_owner, init_domain,
|
|
init_errors, init_request, init_joinable;
|
|
char *init_rdn_value[2], *init_owner_value[2], *init_domain_value[2],
|
|
*init_errors_value[MAX_VALUES], *init_joinable_value[2],
|
|
*init_request_value[MAX_VALUES];
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE) {
|
|
if (name == NULL)
|
|
printf("->add_group(NULL)\n");
|
|
else
|
|
printf("->add_group(%s)\n", name);
|
|
}
|
|
#endif
|
|
|
|
if (bind_status == UD_NOT_BOUND) {
|
|
if (auth((char *) NULL, 1) < 0) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the user did not supply us with a name, prompt them for
|
|
* a name.
|
|
*/
|
|
if ((name == NULL) || (*name == '\0') || !strcasecmp(name, "group")) {
|
|
++prompt;
|
|
printf(" Group to create? ");
|
|
fflush(stdout);
|
|
fetch_buffer(tmp, sizeof(tmp), stdin);
|
|
if (tmp[0] == '\0')
|
|
return;
|
|
name = strdup(tmp);
|
|
}
|
|
|
|
/* remove quotes, dots, and underscores. */
|
|
name = strip_ignore_chars(name);
|
|
|
|
#ifdef UOFM
|
|
if (isauniqname(name)) {
|
|
printf(" '%s' could be confused with a U-M uniqname.\n", name);
|
|
printf(" You can create the group, but you need to make sure that\n");
|
|
printf(" you reserve the uniqname for use as your groupname\n\n");
|
|
printf(" Are you sure that you want to do this? ");
|
|
fflush(stdout);
|
|
fetch_buffer(tmp, sizeof(tmp), stdin);
|
|
if (!(tmp[0] == 'y' || tmp[0] == 'Y'))
|
|
return;
|
|
printf("\n Be sure to contact your uniqname administrator to reserve\n");
|
|
printf(" the uniqname '%s' for use as your group name.\n", name);
|
|
}
|
|
#endif
|
|
sprintf(dn, "cn=%s, %s", name, group_base);
|
|
|
|
/*
|
|
* Make sure that this group does not already exist.
|
|
*/
|
|
if (vrfy(dn) == TRUE) {
|
|
printf(" The group \"%s\" already exists.\n", name);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Take the easy way out: Fill in some reasonable values for
|
|
* the most important fields, and make the user use the modify
|
|
* command to change them, or to give values to other fields.
|
|
*/
|
|
init_rdn_value[0] = name;
|
|
init_rdn_value[1] = NULL;
|
|
init_rdn.mod_op = LDAP_MOD_ADD;
|
|
init_rdn.mod_type = "cn";
|
|
init_rdn.mod_values = init_rdn_value;
|
|
attrs[idx++] = &init_rdn;
|
|
|
|
init_owner_value[0] = bound_dn;
|
|
init_owner_value[1] = NULL;
|
|
init_owner.mod_op = LDAP_MOD_ADD;
|
|
init_owner.mod_type = "owner";
|
|
init_owner.mod_values = init_owner_value;
|
|
attrs[idx++] = &init_owner;
|
|
|
|
#ifdef UOFM
|
|
init_domain_value[0] = "umich.edu";
|
|
#else
|
|
init_domain_value[0] = ".";
|
|
#endif
|
|
init_domain_value[1] = NULL;
|
|
init_domain.mod_op = LDAP_MOD_ADD;
|
|
init_domain.mod_type = "associatedDomain";
|
|
init_domain.mod_values = init_domain_value;
|
|
attrs[idx++] = &init_domain;
|
|
|
|
init_errors_value[0] = bound_dn;
|
|
init_errors_value[1] = NULL;
|
|
init_errors.mod_op = LDAP_MOD_ADD;
|
|
init_errors.mod_type = "ErrorsTo";
|
|
init_errors.mod_values = init_errors_value;
|
|
attrs[idx++] = &init_errors;
|
|
|
|
init_request_value[0] = bound_dn;
|
|
init_request_value[1] = NULL;
|
|
init_request.mod_op = LDAP_MOD_ADD;
|
|
init_request.mod_type = "RequestsTo";
|
|
init_request.mod_values = init_request_value;
|
|
attrs[idx++] = &init_request;
|
|
|
|
init_joinable_value[0] = "FALSE";
|
|
init_joinable_value[1] = NULL;
|
|
init_joinable.mod_op = LDAP_MOD_ADD;
|
|
init_joinable.mod_type = "joinable";
|
|
init_joinable.mod_values = init_joinable_value;
|
|
attrs[idx++] = &init_joinable;
|
|
|
|
/* end it with a NULL */
|
|
attrs[idx] = NULL;
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS) {
|
|
register LDAPMod **lpp;
|
|
register char **cpp;
|
|
register int j;
|
|
printf(" About to call ldap_add()\n");
|
|
printf(" ld = 0x%x\n", ld);
|
|
printf(" dn = [%s]\n", dn);
|
|
for (lpp = attrs, i = 0; *lpp != NULL; lpp++, i++) {
|
|
printf(" attrs[%1d] code = %s type = %s\n", i,
|
|
code_to_str((*lpp)->mod_op), (*lpp)->mod_type);
|
|
for (cpp = (*lpp)->mod_values, j = 0; *cpp != NULL; cpp++, j++)
|
|
printf(" value #%1d = %s\n", j, *cpp);
|
|
printf(" value #%1d = NULL\n", j);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Now add this to the LDAP Directory.
|
|
*/
|
|
if (ldap_add_s(ld, dn, attrs) != 0) {
|
|
ldap_perror(ld, " ldap_add_s");
|
|
printf(" Group not added.\n");
|
|
if (prompt) Free(name);
|
|
return;
|
|
}
|
|
if (verbose)
|
|
printf(" Group \"%s\" has been added to the Directory\n",
|
|
name);
|
|
|
|
/*
|
|
* We need to blow away the cache here.
|
|
*
|
|
* Since we first looked up the name before trying to create it,
|
|
* and that look-up failed, the cache will falsely claim that this
|
|
* entry does not exist.
|
|
*/
|
|
(void) ldap_flush_cache(ld);
|
|
if (prompt) Free(name);
|
|
return;
|
|
}
|
|
|
|
void
|
|
remove_group( char *name )
|
|
{
|
|
char *dn, tmp[BUFSIZ];
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE) {
|
|
if (name == NULL)
|
|
printf("->remove_group(NULL)\n");
|
|
else
|
|
printf("->remove_group(%s)\n", name);
|
|
}
|
|
#endif
|
|
if ((dn = bind_and_fetch(name)) == NULL)
|
|
return;
|
|
|
|
printf("\n The group '%s' will be permanently removed from\n",
|
|
name);
|
|
printf(" the Directory. Are you absolutely sure that you want to\n" ); printf(" remove this entire group? ");
|
|
fflush(stdout);
|
|
fetch_buffer(tmp, sizeof(tmp), stdin);
|
|
if (!(tmp[0] == 'y' || tmp[0] == 'Y'))
|
|
return;
|
|
|
|
/*
|
|
* Now remove this from the LDAP Directory.
|
|
*/
|
|
if (ldap_delete_s(ld, dn) != 0) {
|
|
int ld_errno = 0;
|
|
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
|
|
if (ld_errno == LDAP_INSUFFICIENT_ACCESS)
|
|
printf(" You do not own the group \"%s\".\n", name);
|
|
else
|
|
ldap_perror(ld, " ldap_delete_s");
|
|
printf(" Group not removed.\n");
|
|
Free(dn);
|
|
return;
|
|
}
|
|
ldap_uncache_entry(ld, dn);
|
|
if (verbose)
|
|
if (name == NULL)
|
|
printf(" The group has been removed.\n");
|
|
else
|
|
printf(" The group \"%s\" has been removed.\n", name);
|
|
Free(dn);
|
|
return;
|
|
}
|
|
|
|
void
|
|
x_group( int action, char *name )
|
|
{
|
|
char **vp;
|
|
char *values[2], *group_name;
|
|
LDAPMod mod, *mods[2];
|
|
static char *actions[] = { "join", "resign from", NULL };
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE) {
|
|
if (name == NULL)
|
|
printf("->x_group(%d, NULL)\n", action);
|
|
else
|
|
printf("->x_group(%d, %s)\n", action, name);
|
|
}
|
|
#endif
|
|
|
|
/* the action desired sets the opcode to use */
|
|
switch (action) {
|
|
case G_JOIN:
|
|
mod.mod_op = LDAP_MOD_ADD;
|
|
break;
|
|
case G_RESIGN:
|
|
mod.mod_op = LDAP_MOD_DELETE;
|
|
break;
|
|
default:
|
|
printf("x_group: %d is not a known action\n", action);
|
|
}
|
|
|
|
if ((group_name = bind_and_fetch(name)) == NULL)
|
|
return;
|
|
vp = Entry.attrs[attr_to_index("joinable")].values;
|
|
if (action == G_JOIN) {
|
|
if (vp == NULL) {
|
|
printf(" No one is permitted to join \"%s\"\n", group_name);
|
|
Free(group_name);
|
|
return;
|
|
}
|
|
if (!strcasecmp(*vp, "FALSE")) {
|
|
printf(" No one is permitted to join \"%s\"\n", group_name);
|
|
Free(group_name);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* fill in the rest of the modification structure */
|
|
mods[0] = &mod;
|
|
mods[1] = (LDAPMod *) NULL;
|
|
values[0] = Entry.DN;
|
|
values[1] = NULL;
|
|
mod.mod_type = "memberOfGroup";
|
|
mod.mod_values = values;
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS) {
|
|
register LDAPMod **lpp;
|
|
register char **cp;
|
|
register int i, j;
|
|
printf(" About to call ldap_modify_s()\n");
|
|
printf(" ld = 0x%x\n", ld);
|
|
printf(" dn = [%s]\n", bound_dn);
|
|
for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
|
|
printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
|
|
printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
|
|
for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
|
|
printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (ldap_modify_s(ld, bound_dn, mods)) {
|
|
int ld_errno = 0;
|
|
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
|
|
if ((action == G_JOIN) && (ld_errno == LDAP_TYPE_OR_VALUE_EXISTS))
|
|
printf(" You are already subscribed to \"%s\"\n", group_name);
|
|
else if ((action == G_RESIGN) && (ld_errno == LDAP_NO_SUCH_ATTRIBUTE))
|
|
printf(" You are not subscribed to \"%s\"\n", group_name);
|
|
else
|
|
mod_perror(ld);
|
|
Free(group_name);
|
|
return;
|
|
}
|
|
ldap_uncache_entry(ld, bound_dn);
|
|
if (verbose) {
|
|
switch (action) {
|
|
case G_JOIN:
|
|
printf(" You are now subscribed to \"%s\"\n", group_name);
|
|
break;
|
|
case G_RESIGN:
|
|
printf(" You are no longer subscribed to \"%s\"\n", group_name);
|
|
break;
|
|
}
|
|
}
|
|
Free(group_name);
|
|
return;
|
|
}
|
|
|
|
void
|
|
bulk_load( char *group )
|
|
{
|
|
register int idx_mail, idx_x500;
|
|
register int count_mail, count_x500;
|
|
char *values_mail[MAX_VALUES + 1], *values_x500[MAX_VALUES + 1];
|
|
int added_mail_entries = FALSE, added_x500_entries = FALSE;
|
|
char s[MED_BUF_SIZE];
|
|
LDAPMod mod, *mods[2];
|
|
LDAPMessage *lm;
|
|
FILE *fp;
|
|
int len;
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE)
|
|
printf("->bulk_load(%s)\n", group);
|
|
#endif
|
|
|
|
/* you lose if going through MichNet */
|
|
if ( !isatty( 1 )) {
|
|
#ifdef UOFM
|
|
printf(" Not allowed via UM-X500 connections.\n");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
/* fetch entries from the file containing the e-mail addresses */
|
|
printf("\n File to load? ");
|
|
fflush(stdout);
|
|
fetch_buffer(s, sizeof(s), stdin);
|
|
if (s[0] == '\0') {
|
|
return;
|
|
/*NOTREACHED*/
|
|
}
|
|
if ((fp = fopen(s, "r")) == NULL) {
|
|
perror("bulk_load: fopen");
|
|
return;
|
|
}
|
|
if (verbose)
|
|
printf(" Loading group members from %s\n", s);
|
|
|
|
/* load them in MAX_VALUES at a time */
|
|
for (;;) {
|
|
for (idx_mail = 0, idx_x500 = 0;
|
|
idx_mail < MAX_VALUES && idx_x500 < MAX_VALUES; ) {
|
|
(void) fgets(s, sizeof(s), fp);
|
|
if (feof(fp))
|
|
break;
|
|
len = strlen(s) - 1;
|
|
if (len == 0)
|
|
continue;
|
|
s[len] = '\0';
|
|
if (strchr(s, '@'))
|
|
values_mail[idx_mail++] = strdup(s);
|
|
else {
|
|
if ((lm = find(s, !verbose)) == (LDAPMessage *) NULL) {
|
|
printf(" Could not locate \"%s\" -- skipping.\n", s);
|
|
}
|
|
else {
|
|
parse_answer(lm);
|
|
values_x500[idx_x500++] = strdup(Entry.DN);
|
|
}
|
|
}
|
|
}
|
|
values_mail[idx_mail] = NULL;
|
|
values_x500[idx_x500] = NULL;
|
|
count_mail = idx_mail;
|
|
count_x500 = idx_x500;
|
|
|
|
/*
|
|
* Add the e-mail addresses.
|
|
*/
|
|
if (count_mail > 0) {
|
|
mods[0] = &mod;
|
|
mods[1] = (LDAPMod *) NULL;
|
|
mod.mod_type = "mail";
|
|
mod.mod_values = values_mail;
|
|
if (added_mail_entries)
|
|
mod.mod_op = LDAP_MOD_ADD;
|
|
else
|
|
mod.mod_op = LDAP_MOD_REPLACE;
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS) {
|
|
register LDAPMod **lpp;
|
|
register char **cp;
|
|
register int i, j;
|
|
printf(" About to call ldap_modify_s()\n");
|
|
printf(" ld = 0x%x\n", ld);
|
|
printf(" dn = [%s]\n", group);
|
|
for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
|
|
printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
|
|
printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
|
|
for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
|
|
printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
|
|
}
|
|
}
|
|
#endif
|
|
if (ldap_modify_s(ld, group, mods))
|
|
mod_perror(ld);
|
|
for (idx_mail--; idx_mail >= 0; idx_mail--)
|
|
Free(values_mail[idx_mail]);
|
|
ldap_uncache_entry(ld, group);
|
|
added_mail_entries = TRUE;
|
|
|
|
}
|
|
|
|
/*
|
|
* Add the LDAP style names.
|
|
*/
|
|
if (count_x500 > 0) {
|
|
mods[0] = &mod;
|
|
mods[1] = (LDAPMod *) NULL;
|
|
mod.mod_type = "member";
|
|
mod.mod_values = values_x500;
|
|
if (added_x500_entries)
|
|
mod.mod_op = LDAP_MOD_ADD;
|
|
else
|
|
mod.mod_op = LDAP_MOD_REPLACE;
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS) {
|
|
register LDAPMod **lpp;
|
|
register char **cp;
|
|
register int i, j;
|
|
printf(" About to call ldap_modify_s()\n");
|
|
printf(" ld = 0x%x\n", ld);
|
|
printf(" dn = [%s]\n", group);
|
|
for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
|
|
printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
|
|
printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
|
|
for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
|
|
printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
|
|
}
|
|
}
|
|
#endif
|
|
if (ldap_modify_s(ld, group, mods))
|
|
mod_perror(ld);
|
|
for (idx_x500--; idx_x500 >= 0; idx_x500--)
|
|
Free(values_x500[idx_x500]);
|
|
ldap_uncache_entry(ld, group);
|
|
added_x500_entries = TRUE;
|
|
|
|
}
|
|
|
|
/*
|
|
* If both counts were less than the maximum number we
|
|
* can handle at a time, then we are done.
|
|
*/
|
|
if ((count_mail < MAX_VALUES) && (count_x500 < MAX_VALUES))
|
|
break;
|
|
}
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
|
|
void
|
|
purge_group( char *group )
|
|
{
|
|
int isclean = TRUE;
|
|
LDAPMessage *lm;
|
|
LDAPMod mod, *mods[2];
|
|
char dn[BUFSIZ], tmp[BUFSIZ], *values[2], **vp, **rdns;
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE) {
|
|
if (group == NULL)
|
|
printf("->purge_group(NULL)\n");
|
|
else
|
|
printf("->purge_group(%s)\n", group);
|
|
}
|
|
#endif
|
|
if (bind_status == UD_NOT_BOUND) {
|
|
if (auth((char *) NULL, 1) < 0)
|
|
return;
|
|
}
|
|
/*
|
|
* If the user did not supply us with a name, prompt them for
|
|
* a name.
|
|
*/
|
|
if ((group == NULL) || (*group == '\0')) {
|
|
printf("Group to purge? ");
|
|
fflush(stdout);
|
|
fetch_buffer(tmp, sizeof(tmp), stdin);
|
|
if (tmp[0] == '\0')
|
|
return;
|
|
group = tmp;
|
|
}
|
|
sprintf(dn, "cn=%s, %s", group, group_base);
|
|
|
|
/* make sure the group in question exists */
|
|
if ((lm = find(group, FALSE)) == (LDAPMessage *) NULL) {
|
|
printf(" Could not locate group \"%s\"\n", group);
|
|
return;
|
|
}
|
|
parse_answer(lm);
|
|
ldap_msgfree(lm);
|
|
|
|
/* none of this stuff changes */
|
|
mods[0] = &mod;
|
|
mods[1] = (LDAPMod *) NULL;
|
|
|
|
values[1] = NULL;
|
|
|
|
mod.mod_values = values;
|
|
mod.mod_type = "member";
|
|
mod.mod_op = LDAP_MOD_DELETE;
|
|
|
|
/*
|
|
* Now cycle through all of the names in the "members" part of the
|
|
* group (but not the e-mail address part). Lookup each one, and
|
|
* if it isn't found, let the user know so s/he can delete it.
|
|
*/
|
|
vp = Entry.attrs[attr_to_index("member")].values;
|
|
if (vp == NULL) {
|
|
if (verbose)
|
|
printf(" \"%s\" has no LDAP members. There is nothing to purge.\n", group);
|
|
return;
|
|
}
|
|
for (; *vp != NULL; vp++) {
|
|
char ans[BUFSIZ], *ufn, *label = "Did not find: ";
|
|
int len = strlen(label);
|
|
|
|
if (vrfy(*vp))
|
|
continue;
|
|
isclean = FALSE;
|
|
ufn = my_ldap_dn2ufn(*vp);
|
|
format2(ufn, label, (char *) NULL, 2, 2 + len, col_size);
|
|
ask:
|
|
printf(" Purge, Keep, Replace, Abort [Keep]? ");
|
|
fflush(stdout);
|
|
fetch_buffer(ans, sizeof(ans), stdin);
|
|
if ((ans[0] == '\0') || !strncasecmp(ans, "Keep", strlen(ans)))
|
|
continue;
|
|
if (!strncasecmp(ans, "Abort", strlen(ans))) {
|
|
ldap_uncache_entry(ld, dn);
|
|
return;
|
|
}
|
|
if (!strncasecmp(ans, "Purge", strlen(ans)) || !strncasecmp(ans, "Replace", strlen(ans))) {
|
|
values[0] = *vp;
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS) {
|
|
register LDAPMod **lpp;
|
|
register char **cp;
|
|
register int i, j;
|
|
printf(" About to call ldap_modify_s()\n");
|
|
printf(" ld = 0x%x\n", ld);
|
|
printf(" dn = [%s]\n", Entry.DN);
|
|
for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
|
|
printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
|
|
printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
|
|
for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
|
|
printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
|
|
|
|
}
|
|
}
|
|
#endif
|
|
if (ldap_modify_s(ld, Entry.DN, mods))
|
|
mod_perror(ld);
|
|
|
|
/* now add the replacement if requested */
|
|
if (!strncasecmp(ans, "Purge", strlen(ans)))
|
|
continue;
|
|
rdns = ldap_explode_dn(*vp, TRUE);
|
|
if ((lm = find(*rdns, FALSE)) == NULL) {
|
|
printf(" Could not find a replacement for %s; purged only.\n", *rdns);
|
|
ldap_msgfree(lm);
|
|
ldap_value_free(rdns);
|
|
break;
|
|
}
|
|
values[0] = ldap_get_dn(ld, ldap_first_entry(ld, lm));
|
|
mod.mod_op = LDAP_MOD_ADD;
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS) {
|
|
register LDAPMod **lpp;
|
|
register char **cp;
|
|
register int i, j;
|
|
printf(" About to call ldap_modify_s()\n");
|
|
printf(" ld = 0x%x\n", ld);
|
|
printf(" dn = [%s]\n", Entry.DN);
|
|
for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
|
|
printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
|
|
printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
|
|
for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
|
|
printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
|
|
|
|
}
|
|
}
|
|
#endif
|
|
if (ldap_modify_s(ld, Entry.DN, mods))
|
|
mod_perror(ld);
|
|
ldap_msgfree(lm);
|
|
ldap_value_free(rdns);
|
|
|
|
/* set this back to DELETE for other purges */
|
|
mod.mod_op = LDAP_MOD_DELETE;
|
|
}
|
|
else {
|
|
printf(" Did not recognize that answer.\n\n");
|
|
goto ask;
|
|
}
|
|
}
|
|
ldap_uncache_entry(ld, Entry.DN);
|
|
if (isclean)
|
|
printf(" No entries were purged.\n");
|
|
return;
|
|
}
|
|
|
|
void
|
|
tidy_up( void )
|
|
{
|
|
register int i = 0;
|
|
int found_one = 0;
|
|
register char **vp;
|
|
LDAPMessage *lm;
|
|
static LDAPMod mod;
|
|
static LDAPMod *mods[2] = { &mod, NULL };
|
|
static char *values[MAX_VALUES];
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE)
|
|
printf("->tidy()\n");
|
|
#endif
|
|
|
|
if (bind_status == UD_NOT_BOUND) {
|
|
if (auth((char *) NULL, 1) < 0) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* lookup the user, and see to which groups he has subscribed */
|
|
vp = ldap_explode_dn(bound_dn, TRUE);
|
|
if ((lm = find(*vp, TRUE)) == (LDAPMessage *) NULL) {
|
|
printf(" Could not locate \"%s\"\n", *vp);
|
|
ldap_value_free(vp);
|
|
return;
|
|
}
|
|
ldap_value_free(vp);
|
|
parse_answer(lm);
|
|
ldap_msgfree(lm);
|
|
vp = Entry.attrs[attr_to_index("memberOfGroup")].values;
|
|
if (vp == NULL) {
|
|
printf(" You have not subscribed to any groups.\n");
|
|
return;
|
|
}
|
|
|
|
/* now, loop through these groups, deleting the bogus */
|
|
for ( ; *vp != NULL; vp++) {
|
|
if (vrfy(*vp))
|
|
continue;
|
|
found_one++;
|
|
printf(" \"%s\" is not a valid group name.\n", *vp);
|
|
values[i++] = strdup(*vp);
|
|
if ( i >= MAX_VALUES ) {
|
|
printf( " At most %d invalid groups can be removed at one time; skipping the rest.\n", MAX_VALUES );
|
|
break;
|
|
}
|
|
}
|
|
if (found_one == 0) {
|
|
if (verbose)
|
|
printf(" You are not a member of any invalid groups. There is nothing to tidy.\n");
|
|
return;
|
|
}
|
|
|
|
/* delete the most heinous entries */
|
|
values[i] = NULL;
|
|
mod.mod_values = values;
|
|
mod.mod_op = LDAP_MOD_DELETE;
|
|
mod.mod_type = "memberOfGroup";
|
|
if (ldap_modify_s(ld, bound_dn, mods))
|
|
mod_perror(ld);
|
|
ldap_uncache_entry(ld, bound_dn);
|
|
|
|
/* tidy up before we finish tidy_up */
|
|
for ( ; i >= 1; i--)
|
|
Free(values[i - 1]);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* This routine is used to modify lists that can contain either Distinguished
|
|
* Names or e-mail addresses. This includes things like group members,
|
|
* the errors-to field in groups, and so on.
|
|
*/
|
|
void
|
|
mod_addrDN( char *group, int offset )
|
|
{
|
|
char s[BUFSIZ], *new_value /* was member */, *values[2];
|
|
char attrtype[ 64 ];
|
|
int i;
|
|
LDAPMod mod, *mods[2];
|
|
LDAPMessage *mp;
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE)
|
|
printf("->mod_addrDN(%s)\n", group);
|
|
#endif
|
|
/*
|
|
* At this point the user can indicate that he wishes to add values
|
|
* to the attribute, delete values from the attribute, or replace the
|
|
* current list of values with a new list. The first two cases
|
|
* are very straight-forward, but the last case requires a little
|
|
* extra care and work.
|
|
*/
|
|
if (verbose) {
|
|
printf("\n");
|
|
if ( !isatty( 1 ))
|
|
format("There are three options available at this point. You may: Add additional values; Delete values; or Replace the entire list of values with a new list entered interactively.\n", 75, 2);
|
|
else
|
|
format("There are four options available at this point. You may: Add one or more additional values; Delete one or more existing values; Replace the entire list of values with a new list entered interactively; or Bulk load a new list of values from a file, overwriting the existing list.\n", 75, 2);
|
|
}
|
|
|
|
/* initialize the modififier type */
|
|
mod.mod_type = NULL;
|
|
|
|
for (;;) {
|
|
if ( !isatty( 1 ))
|
|
printf(" Do you want to Add, Delete, or Replace? ");
|
|
else
|
|
printf(" Do you want to Add, Delete, Replace, or Bulk load? ");
|
|
fflush(stdout);
|
|
fetch_buffer(s, sizeof(s), stdin);
|
|
if (s[0] == '\0') {
|
|
return;
|
|
/*NOTREACHED*/
|
|
}
|
|
if (!strncasecmp(s, "add", strlen(s))) {
|
|
mod.mod_op = LDAP_MOD_ADD;
|
|
break;
|
|
}
|
|
else if (!strncasecmp(s, "delete", strlen(s))) {
|
|
mod.mod_op = LDAP_MOD_DELETE;
|
|
break;
|
|
}
|
|
else if (!strncasecmp(s, "replace", strlen(s))) {
|
|
mod.mod_op = LDAP_MOD_REPLACE;
|
|
break;
|
|
}
|
|
else if(!strncasecmp(s, "bulk", strlen(s))) {
|
|
bulk_load(group);
|
|
return;
|
|
}
|
|
else if (verbose) {
|
|
printf("\n");
|
|
if ( !isatty( 1 ))
|
|
format("Did not recognize that response. Please use 'A' to add, 'D' to delete, or 'R' to replace the entire list with a new list\n", 75, 2);
|
|
else
|
|
format("Did not recognize that response. Please use 'A' to add, 'D' to delete, 'R' to replace the entire list with a new list, or 'B' to bulk load a new list from a file\n", 75, 2);
|
|
}
|
|
}
|
|
if (mod.mod_op == LDAP_MOD_REPLACE) {
|
|
if ( verbose && !confirm_action( "The entire existing list will be overwritten with the new values you are about to enter." )) {
|
|
printf("\n Modification halted.\n");
|
|
return;
|
|
}
|
|
}
|
|
if (verbose) {
|
|
printf("\n");
|
|
format("Values may be specified as a name (which is then looked up in the LDAP Directory) or as a domain-style (i.e., user@domain) e-mail address. Simply hit the RETURN key at the prompt when finished.\n", 75, 2);
|
|
printf("\n");
|
|
}
|
|
|
|
for (;;) {
|
|
printf("%s? ", attrlist[offset].output_string);
|
|
fflush(stdout);
|
|
fetch_buffer(s, sizeof(s), stdin);
|
|
if (s[0] == '\0')
|
|
return;
|
|
|
|
/*
|
|
* If the string the user has just typed has an @-sign in it,
|
|
* then we assume it is an e-mail address. In this case, we
|
|
* just store away whatever it is they have typed.
|
|
*
|
|
* If the string had no @-sign, then we look in the Directory,
|
|
* make sure it exists, and if it does, we add that.
|
|
*
|
|
* If the string begins with a comma, then strip off the
|
|
* comma, and pass it along to the LDAP server. This is
|
|
* the way one can force ud to accept a name. Handy for
|
|
* debugging purposes.
|
|
*/
|
|
if (*s == ',') {
|
|
new_value = s + 1;
|
|
mod.mod_type = attrlist[offset].quipu_name;
|
|
}
|
|
else if (strchr(s, '@') == NULL) {
|
|
if ((mp = find(s, FALSE)) == (LDAPMessage *) NULL) {
|
|
printf(" Could not find \"%s\"\n", s);
|
|
if (verbose && (mod.mod_op == LDAP_MOD_DELETE)){
|
|
printf("\n");
|
|
format("I could not find anything that matched what you typed. You might try the \"purge\" command instead. It is used to purge corrupted or unlocatable entries from a group.", 75, 2);
|
|
printf("\n");
|
|
}
|
|
continue;
|
|
}
|
|
parse_answer(mp);
|
|
new_value = Entry.DN;
|
|
mod.mod_type = attrlist[offset].quipu_name;
|
|
}
|
|
else if (mod.mod_op != LDAP_MOD_DELETE) {
|
|
/*
|
|
* Don't screw around with what the user has typed
|
|
* if they are simply trying to delete a rfc822mailbox
|
|
* value.
|
|
*
|
|
* spaces on the left hand side of the e-mail
|
|
* address are bad news - we know that there
|
|
* must be a @-sign in the string, or else we
|
|
* would not be here
|
|
*
|
|
* note that this means a value like:
|
|
*
|
|
* first m. last@host.domain
|
|
*
|
|
* will be turned into:
|
|
*
|
|
* first.m..last@host.domain
|
|
*
|
|
* and the mailer will need to do the right thing
|
|
* with this; alternatively we could add code that
|
|
* collapsed multiple dots into a single dot
|
|
*
|
|
* Don't screw up things like:
|
|
*
|
|
* "Bryan Beecher" <bryan@umich.edu>
|
|
* Bryan Beecher <bryan@umich.edu>
|
|
*/
|
|
register char *cp;
|
|
if (strchr(s, '<') == NULL) {
|
|
for (cp = s; *cp != '@'; cp++)
|
|
if (isspace(*cp))
|
|
*cp = '.';
|
|
}
|
|
new_value = s;
|
|
strcpy(attrtype, "rfc822");
|
|
strcat(attrtype, attrlist[offset].quipu_name);
|
|
mod.mod_type = attrtype;
|
|
}
|
|
else {
|
|
new_value = s;
|
|
strcpy(attrtype, "rfc822");
|
|
strcat(attrtype, attrlist[offset].quipu_name);
|
|
mod.mod_type = attrtype;
|
|
}
|
|
|
|
/* fill in the rest of the ldap_mod() structure */
|
|
mods[0] = &mod;
|
|
mods[1] = (LDAPMod *) NULL;
|
|
|
|
values[0] = new_value;
|
|
values[1] = NULL;
|
|
mod.mod_values = values;
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS) {
|
|
register LDAPMod **lpp;
|
|
register char **cp;
|
|
register int i, j;
|
|
printf(" About to call ldap_modify_s()\n");
|
|
printf(" ld = 0x%x\n", ld);
|
|
printf(" dn = [%s]\n", group);
|
|
for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
|
|
printf(" mods[%1d] code = %1d\n",
|
|
i, (*lpp)->mod_op);
|
|
printf(" mods[%1d] type = %s\n",
|
|
i, (*lpp)->mod_type);
|
|
for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
|
|
printf(" mods[%1d] v[%1d] = %s\n",
|
|
i, j, *cp);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (my_ldap_modify_s(ld, group, mods)) {
|
|
int ld_errno = 0;
|
|
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
|
|
if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE) {
|
|
printf(" Could not locate value \"%s\"\n",
|
|
new_value);
|
|
continue;
|
|
}
|
|
else {
|
|
mod_perror(ld);
|
|
return;
|
|
}
|
|
}
|
|
ldap_uncache_entry(ld, group);
|
|
|
|
/*
|
|
* If the operation was REPLACE, we now need to "zero out" the
|
|
* other "half" of the list (e.g., user specified an e-mail
|
|
* address; now we need to clear the DN part of the list).
|
|
*
|
|
* NOTE: WE HAVE ALREADY DONE HALF OF THE REPLACE ABOVE.
|
|
*
|
|
* Also, change the opcode to LDAP_MOD_ADD and give the user an
|
|
* opportunity to add additional members to the group. We
|
|
* only take this branch the very first time during a REPLACE
|
|
* operation.
|
|
*/
|
|
if (mod.mod_op == LDAP_MOD_REPLACE) {
|
|
if (!strncmp(mod.mod_type, "rfc822", 6))
|
|
mod.mod_type = mod.mod_type + 6;
|
|
else {
|
|
strcpy(attrtype, "rfc822");
|
|
strcat(attrtype, mod.mod_type);
|
|
mod.mod_type = attrtype;
|
|
}
|
|
mods[0] = &mod;
|
|
values[0] = NULL;
|
|
mod.mod_values = values;
|
|
mod.mod_op = LDAP_MOD_DELETE;
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS) {
|
|
register LDAPMod **lpp;
|
|
register char **cp;
|
|
register int i, j;
|
|
printf(" About to call ldap_modify_s()\n");
|
|
printf(" ld = 0x%x\n", ld);
|
|
printf(" dn = [%s]\n", group);
|
|
for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
|
|
printf(" mods[%1d] code = %1d\n",
|
|
i, (*lpp)->mod_op);
|
|
printf(" mods[%1d] type = %s\n",
|
|
i, (*lpp)->mod_type);
|
|
for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
|
|
printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
|
|
}
|
|
}
|
|
#endif
|
|
if (my_ldap_modify_s(ld, group, mods)) {
|
|
/*
|
|
* A "No such attribute" error is no big deal.
|
|
* We only wanted to clear the attribute anyhow.
|
|
*/
|
|
int ld_errno = 0;
|
|
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
|
|
if (ld_errno != LDAP_NO_SUCH_ATTRIBUTE) {
|
|
mod_perror(ld);
|
|
return;
|
|
}
|
|
}
|
|
ldap_uncache_entry(ld, group);
|
|
if (verbose)
|
|
printf(" \"%s\" has been added\n", new_value);
|
|
mod.mod_op = LDAP_MOD_ADD;
|
|
}
|
|
else if (verbose && (mod.mod_op == LDAP_MOD_ADD))
|
|
printf(" \"%s\" has been added\n", new_value);
|
|
else if (verbose && (mod.mod_op == LDAP_MOD_DELETE))
|
|
printf(" \"%s\" has been removed\n", new_value);
|
|
}
|
|
}
|
|
|
|
int
|
|
my_ldap_modify_s( LDAP *ldap, char *group, LDAPMod **mods )
|
|
{
|
|
int was_rfc822member, rc;
|
|
|
|
was_rfc822member = 0;
|
|
|
|
if (!strcasecmp(mods[0]->mod_type, "rfc822member")) {
|
|
mods[0]->mod_type = "mail";
|
|
was_rfc822member = 1;
|
|
}
|
|
|
|
rc = ldap_modify_s(ldap, group, mods);
|
|
|
|
if (was_rfc822member)
|
|
mods[0]->mod_type = "rfc822member";
|
|
|
|
return(rc);
|
|
}
|
|
|
|
void
|
|
list_groups( char *who )
|
|
{
|
|
LDAPMessage *mp;
|
|
char name[BUFSIZ], filter[BUFSIZ], *search_attrs[2];
|
|
char *work_area[MAX_NUM_NAMES];
|
|
char *dn, **rdns;
|
|
int i, rc;
|
|
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE) {
|
|
if (who == NULL)
|
|
printf("->list_groups(NULL)\n");
|
|
else
|
|
printf("->list_groups(%s)\n", who);
|
|
}
|
|
#endif
|
|
/*
|
|
* First, decide what entry we are going to list. If the
|
|
* user has not included a name on the list command line,
|
|
* we will use the person who was last looked up with a find
|
|
* command.
|
|
*
|
|
* Once we know who to modify, be sure that they exist, and
|
|
* parse out their DN.
|
|
*/
|
|
if (who == NULL) {
|
|
printf(" List groups belonging to whose entry? ");
|
|
fflush(stdout);
|
|
fetch_buffer(name, sizeof(name), stdin);
|
|
if (name[0] != '\0')
|
|
who = name;
|
|
else
|
|
return;
|
|
}
|
|
if ((mp = find(who, TRUE)) == NULL) {
|
|
(void) ldap_msgfree(mp);
|
|
printf(" Could not locate \"%s\" in the Directory.\n", who);
|
|
return;
|
|
}
|
|
dn = ldap_get_dn(ld, ldap_first_entry(ld, mp));
|
|
ldap_msgfree(mp);
|
|
rdns = ldap_explode_dn(dn, TRUE);
|
|
if (verbose)
|
|
printf("\n Listing groups belonging to \"%s\"\n", *rdns);
|
|
|
|
/* lookup the groups belonging to this person */
|
|
sprintf(filter, "owner=%s", dn);
|
|
Free(dn);
|
|
search_attrs[0] = "cn";
|
|
search_attrs[1] = NULL;
|
|
if ((rc = ldap_search_s(ld, UD_WHERE_ALL_GROUPS_LIVE, LDAP_SCOPE_SUBTREE,
|
|
filter, search_attrs, FALSE, &mp)) != LDAP_SUCCESS &&
|
|
rc != LDAP_SIZELIMIT_EXCEEDED && rc != LDAP_TIMELIMIT_EXCEEDED) {
|
|
ldap_perror(ld, "ldap_search_s");
|
|
ldap_value_free(rdns);
|
|
return;
|
|
}
|
|
if ((rc = ldap_count_entries(ld, mp)) < 0) {
|
|
ldap_perror(ld, "ldap_count_entries");
|
|
ldap_value_free(rdns);
|
|
return;
|
|
}
|
|
if (rc == 0) {
|
|
printf(" %s owns no groups in this portion of the Directory.\n", *rdns);
|
|
ldap_value_free(rdns);
|
|
return;
|
|
}
|
|
if (verbose)
|
|
printf(" %s owns %d groups.\n\n", *rdns, rc);
|
|
print_list(mp, work_area, &rc);
|
|
for (i = 1; work_area[i] != NULL; i++)
|
|
Free(work_area[i]);
|
|
ldap_msgfree(mp);
|
|
ldap_value_free(rdns);
|
|
return;
|
|
}
|
|
|
|
static char *
|
|
bind_and_fetch( char *name )
|
|
{
|
|
LDAPMessage *lm;
|
|
char tmp[MED_BUF_SIZE];
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE) {
|
|
if (name == NULL)
|
|
printf("->bind_and_fetch(NULL)\n");
|
|
else
|
|
printf("->bind_and_fetch(%s)\n", name);
|
|
}
|
|
#endif
|
|
if (bind_status == UD_NOT_BOUND) {
|
|
if (auth((char *) NULL, 1) < 0)
|
|
return(NULL);
|
|
}
|
|
|
|
/*
|
|
* If the user did not supply us with a name, prompt them for
|
|
* a name.
|
|
*/
|
|
if ((name == NULL) || (*name == '\0')) {
|
|
printf(" Group? ");
|
|
fflush(stdout);
|
|
fetch_buffer(tmp, sizeof(tmp), stdin);
|
|
if (tmp[0] == '\0')
|
|
return(NULL);
|
|
name = tmp;
|
|
}
|
|
/* remove quotes, dots, and underscores. */
|
|
name = strip_ignore_chars(name);
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS)
|
|
printf("Group name = (%s)\n", name);
|
|
#endif
|
|
|
|
/* make sure the group in question exists and is joinable */
|
|
if ((lm = find(name, TRUE)) == (LDAPMessage *) NULL) {
|
|
printf(" Could not locate group \"%s\"\n", name);
|
|
return(NULL);
|
|
}
|
|
parse_answer(lm);
|
|
ldap_msgfree(lm);
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_GROUPS)
|
|
printf("Group DN = (%s)\n", Entry.DN);
|
|
#endif
|
|
return(strdup(Entry.DN));
|
|
}
|
|
|
|
void
|
|
list_memberships( char *who )
|
|
{
|
|
LDAPMessage *mp;
|
|
char name[BUFSIZ], filter[BUFSIZ], *search_attrs[2];
|
|
char *work_area[MAX_NUM_NAMES];
|
|
char *dn, **rdns;
|
|
int i, rc;
|
|
|
|
|
|
#ifdef DEBUG
|
|
if (debug & D_TRACE) {
|
|
if (who == NULL)
|
|
printf("->list_memberships(NULL)\n");
|
|
else
|
|
printf("->list_memberships(%s)\n", who);
|
|
}
|
|
#endif
|
|
/*
|
|
* First, decide what entry we are going to list. If the
|
|
* user has not included a name on the list command line,
|
|
* we will use the person who was last looked up with a find
|
|
* command.
|
|
*
|
|
* Once we know who to modify, be sure that they exist, and
|
|
* parse out their DN.
|
|
*/
|
|
if (who == NULL) {
|
|
printf(" List memberships containing whose entry? ");
|
|
fflush(stdout);
|
|
fetch_buffer(name, sizeof(name), stdin);
|
|
if (name[0] != '\0')
|
|
who = name;
|
|
else
|
|
return;
|
|
}
|
|
if ((mp = find(who, TRUE)) == NULL) {
|
|
(void) ldap_msgfree(mp);
|
|
printf(" Could not locate \"%s\" in the Directory.\n", who);
|
|
ldap_msgfree(mp);
|
|
return;
|
|
}
|
|
dn = ldap_get_dn(ld, ldap_first_entry(ld, mp));
|
|
rdns = ldap_explode_dn(dn, TRUE);
|
|
if (verbose)
|
|
printf("\n Listing memberships of \"%s\"\n", *rdns);
|
|
|
|
/* lookup the groups belonging to this person */
|
|
sprintf(filter, "member=%s", dn);
|
|
Free(dn);
|
|
search_attrs[0] = "cn";
|
|
search_attrs[1] = NULL;
|
|
ldap_msgfree(mp);
|
|
if ((rc = ldap_search_s(ld, UD_WHERE_ALL_GROUPS_LIVE, LDAP_SCOPE_SUBTREE,
|
|
filter, search_attrs, FALSE, &mp)) != LDAP_SUCCESS &&
|
|
rc != LDAP_SIZELIMIT_EXCEEDED && rc != LDAP_TIMELIMIT_EXCEEDED) {
|
|
ldap_perror(ld, "ldap_search_s");
|
|
ldap_msgfree(mp);
|
|
ldap_value_free(rdns);
|
|
return;
|
|
}
|
|
if ((rc = ldap_count_entries(ld, mp)) < 0) {
|
|
ldap_perror(ld, "ldap_count_entries");
|
|
ldap_msgfree(mp);
|
|
ldap_value_free(rdns);
|
|
return;
|
|
}
|
|
if (rc == 0) {
|
|
printf(" %s is not a member of any groups in this portion of the Directory.\n", *rdns);
|
|
ldap_msgfree(mp);
|
|
ldap_value_free(rdns);
|
|
return;
|
|
}
|
|
if (verbose)
|
|
printf(" %s is a member of %d groups.\n\n", *rdns, rc);
|
|
|
|
/*
|
|
* print_list fills in the char * array starting at 1, not 0
|
|
*/
|
|
print_list(mp, work_area, &rc);
|
|
for (i = 1; work_area[i] != NULL; i++)
|
|
Free(work_area[i]);
|
|
ldap_msgfree(mp);
|
|
ldap_value_free(rdns);
|
|
return;
|
|
}
|