2 * Copyright (c) 1993, 1994 Regents of the University of Michigan.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of Michigan at Ann Arbor. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
18 #include <ac/string.h>
21 #include <ac/unistd.h>
25 #include <ldapconfig.h>
28 static char * bind_and_fetch(char *name);
32 add_group( char *name )
34 register int i, idx = 0, prompt = 0;
35 char tmp[BUFSIZ], dn[BUFSIZ];
36 static LDAPMod *attrs[9];
37 LDAPMod init_rdn, init_owner, init_domain,
38 init_errors, init_request, init_joinable;
39 char *init_rdn_value[2], *init_owner_value[2], *init_domain_value[2],
40 *init_errors_value[MAX_VALUES], *init_joinable_value[2],
41 *init_request_value[MAX_VALUES];
44 if (debug & D_TRACE) {
46 printf("->add_group(NULL)\n");
48 printf("->add_group(%s)\n", name);
52 if (bind_status == UD_NOT_BOUND) {
53 if (auth((char *) NULL, 1) < 0) {
59 * If the user did not supply us with a name, prompt them for
62 if ((name == NULL) || (*name == '\0') || !strcasecmp(name, "group")) {
64 printf(" Group to create? ");
66 fetch_buffer(tmp, sizeof(tmp), stdin);
72 /* remove quotes, dots, and underscores. */
73 name = strip_ignore_chars(name);
76 if (isauniqname(name)) {
77 printf(" '%s' could be confused with a U-M uniqname.\n", name);
78 printf(" You can create the group, but you need to make sure that\n");
79 printf(" you reserve the uniqname for use as your groupname\n\n");
80 printf(" Are you sure that you want to do this? ");
82 fetch_buffer(tmp, sizeof(tmp), stdin);
83 if (!(tmp[0] == 'y' || tmp[0] == 'Y'))
85 printf("\n Be sure to contact your uniqname administrator to reserve\n");
86 printf(" the uniqname '%s' for use as your group name.\n", name);
89 sprintf(dn, "cn=%s, %s", name, group_base);
92 * Make sure that this group does not already exist.
94 if (vrfy(dn) == TRUE) {
95 printf(" The group \"%s\" already exists.\n", name);
100 * Take the easy way out: Fill in some reasonable values for
101 * the most important fields, and make the user use the modify
102 * command to change them, or to give values to other fields.
104 init_rdn_value[0] = name;
105 init_rdn_value[1] = NULL;
106 init_rdn.mod_op = LDAP_MOD_ADD;
107 init_rdn.mod_type = "cn";
108 init_rdn.mod_values = init_rdn_value;
109 attrs[idx++] = &init_rdn;
111 init_owner_value[0] = bound_dn;
112 init_owner_value[1] = NULL;
113 init_owner.mod_op = LDAP_MOD_ADD;
114 init_owner.mod_type = "owner";
115 init_owner.mod_values = init_owner_value;
116 attrs[idx++] = &init_owner;
119 init_domain_value[0] = "umich.edu";
121 init_domain_value[0] = ".";
123 init_domain_value[1] = NULL;
124 init_domain.mod_op = LDAP_MOD_ADD;
125 init_domain.mod_type = "associatedDomain";
126 init_domain.mod_values = init_domain_value;
127 attrs[idx++] = &init_domain;
129 init_errors_value[0] = bound_dn;
130 init_errors_value[1] = NULL;
131 init_errors.mod_op = LDAP_MOD_ADD;
132 init_errors.mod_type = "ErrorsTo";
133 init_errors.mod_values = init_errors_value;
134 attrs[idx++] = &init_errors;
136 init_request_value[0] = bound_dn;
137 init_request_value[1] = NULL;
138 init_request.mod_op = LDAP_MOD_ADD;
139 init_request.mod_type = "RequestsTo";
140 init_request.mod_values = init_request_value;
141 attrs[idx++] = &init_request;
143 init_joinable_value[0] = "FALSE";
144 init_joinable_value[1] = NULL;
145 init_joinable.mod_op = LDAP_MOD_ADD;
146 init_joinable.mod_type = "joinable";
147 init_joinable.mod_values = init_joinable_value;
148 attrs[idx++] = &init_joinable;
150 /* end it with a NULL */
154 if (debug & D_GROUPS) {
155 register LDAPMod **lpp;
158 printf(" About to call ldap_add()\n");
159 printf(" ld = 0x%x\n", ld);
160 printf(" dn = [%s]\n", dn);
161 for (lpp = attrs, i = 0; *lpp != NULL; lpp++, i++) {
162 printf(" attrs[%1d] code = %s type = %s\n", i,
163 code_to_str((*lpp)->mod_op), (*lpp)->mod_type);
164 for (cpp = (*lpp)->mod_values, j = 0; *cpp != NULL; cpp++, j++)
165 printf(" value #%1d = %s\n", j, *cpp);
166 printf(" value #%1d = NULL\n", j);
172 * Now add this to the LDAP Directory.
174 if (ldap_add_s(ld, dn, attrs) != 0) {
175 ldap_perror(ld, " ldap_add_s");
176 printf(" Group not added.\n");
177 if (prompt) Free(name);
181 printf(" Group \"%s\" has been added to the Directory\n",
185 * We need to blow away the cache here.
187 * Since we first looked up the name before trying to create it,
188 * and that look-up failed, the cache will falsely claim that this
189 * entry does not exist.
191 (void) ldap_flush_cache(ld);
192 if (prompt) Free(name);
197 remove_group( char *name )
199 char *dn, tmp[BUFSIZ];
202 if (debug & D_TRACE) {
204 printf("->remove_group(NULL)\n");
206 printf("->remove_group(%s)\n", name);
209 if ((dn = bind_and_fetch(name)) == NULL)
212 printf("\n The group '%s' will be permanently removed from\n",
214 printf(" the Directory. Are you absolutely sure that you want to\n" ); printf(" remove this entire group? ");
216 fetch_buffer(tmp, sizeof(tmp), stdin);
217 if (!(tmp[0] == 'y' || tmp[0] == 'Y'))
221 * Now remove this from the LDAP Directory.
223 if (ldap_delete_s(ld, dn) != 0) {
225 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
226 if (ld_errno == LDAP_INSUFFICIENT_ACCESS)
227 printf(" You do not own the group \"%s\".\n", name);
229 ldap_perror(ld, " ldap_delete_s");
230 printf(" Group not removed.\n");
234 ldap_uncache_entry(ld, dn);
237 printf(" The group has been removed.\n");
239 printf(" The group \"%s\" has been removed.\n", name);
245 x_group( int action, char *name )
248 char *values[2], *group_name;
249 LDAPMod mod, *mods[2];
250 static char *actions[] = { "join", "resign from", NULL };
253 if (debug & D_TRACE) {
255 printf("->x_group(%d, NULL)\n", action);
257 printf("->x_group(%d, %s)\n", action, name);
261 /* the action desired sets the opcode to use */
264 mod.mod_op = LDAP_MOD_ADD;
267 mod.mod_op = LDAP_MOD_DELETE;
270 printf("x_group: %d is not a known action\n", action);
273 if ((group_name = bind_and_fetch(name)) == NULL)
275 vp = Entry.attrs[attr_to_index("joinable")].values;
276 if (action == G_JOIN) {
278 printf(" No one is permitted to join \"%s\"\n", group_name);
282 if (!strcasecmp(*vp, "FALSE")) {
283 printf(" No one is permitted to join \"%s\"\n", group_name);
289 /* fill in the rest of the modification structure */
291 mods[1] = (LDAPMod *) NULL;
292 values[0] = Entry.DN;
294 mod.mod_type = "memberOfGroup";
295 mod.mod_values = values;
298 if (debug & D_GROUPS) {
299 register LDAPMod **lpp;
302 printf(" About to call ldap_modify_s()\n");
303 printf(" ld = 0x%x\n", ld);
304 printf(" dn = [%s]\n", bound_dn);
305 for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
306 printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
307 printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
308 for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
309 printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
315 if (ldap_modify_s(ld, bound_dn, mods)) {
317 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
318 if ((action == G_JOIN) && (ld_errno == LDAP_TYPE_OR_VALUE_EXISTS))
319 printf(" You are already subscribed to \"%s\"\n", group_name);
320 else if ((action == G_RESIGN) && (ld_errno == LDAP_NO_SUCH_ATTRIBUTE))
321 printf(" You are not subscribed to \"%s\"\n", group_name);
327 ldap_uncache_entry(ld, bound_dn);
331 printf(" You are now subscribed to \"%s\"\n", group_name);
334 printf(" You are no longer subscribed to \"%s\"\n", group_name);
343 bulk_load( char *group )
345 register int idx_mail, idx_x500;
346 register int count_mail, count_x500;
347 char *values_mail[MAX_VALUES + 1], *values_x500[MAX_VALUES + 1];
348 int added_mail_entries = FALSE, added_x500_entries = FALSE;
349 char s[MED_BUF_SIZE];
350 LDAPMod mod, *mods[2];
357 printf("->bulk_load(%s)\n", group);
360 /* you lose if going through MichNet */
363 printf(" Not allowed via UM-X500 connections.\n");
368 /* fetch entries from the file containing the e-mail addresses */
369 printf("\n File to load? ");
371 fetch_buffer(s, sizeof(s), stdin);
376 if ((fp = fopen(s, "r")) == NULL) {
377 perror("bulk_load: fopen");
381 printf(" Loading group members from %s\n", s);
383 /* load them in MAX_VALUES at a time */
385 for (idx_mail = 0, idx_x500 = 0;
386 idx_mail < MAX_VALUES && idx_x500 < MAX_VALUES; ) {
387 (void) fgets(s, sizeof(s), fp);
395 values_mail[idx_mail++] = strdup(s);
397 if ((lm = find(s, !verbose)) == (LDAPMessage *) NULL) {
398 printf(" Could not locate \"%s\" -- skipping.\n", s);
402 values_x500[idx_x500++] = strdup(Entry.DN);
406 values_mail[idx_mail] = NULL;
407 values_x500[idx_x500] = NULL;
408 count_mail = idx_mail;
409 count_x500 = idx_x500;
412 * Add the e-mail addresses.
414 if (count_mail > 0) {
416 mods[1] = (LDAPMod *) NULL;
417 mod.mod_type = "mail";
418 mod.mod_values = values_mail;
419 if (added_mail_entries)
420 mod.mod_op = LDAP_MOD_ADD;
422 mod.mod_op = LDAP_MOD_REPLACE;
425 if (debug & D_GROUPS) {
426 register LDAPMod **lpp;
429 printf(" About to call ldap_modify_s()\n");
430 printf(" ld = 0x%x\n", ld);
431 printf(" dn = [%s]\n", group);
432 for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
433 printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
434 printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
435 for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
436 printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
440 if (ldap_modify_s(ld, group, mods))
442 for (idx_mail--; idx_mail >= 0; idx_mail--)
443 Free(values_mail[idx_mail]);
444 ldap_uncache_entry(ld, group);
445 added_mail_entries = TRUE;
450 * Add the LDAP style names.
452 if (count_x500 > 0) {
454 mods[1] = (LDAPMod *) NULL;
455 mod.mod_type = "member";
456 mod.mod_values = values_x500;
457 if (added_x500_entries)
458 mod.mod_op = LDAP_MOD_ADD;
460 mod.mod_op = LDAP_MOD_REPLACE;
463 if (debug & D_GROUPS) {
464 register LDAPMod **lpp;
467 printf(" About to call ldap_modify_s()\n");
468 printf(" ld = 0x%x\n", ld);
469 printf(" dn = [%s]\n", group);
470 for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
471 printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
472 printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
473 for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
474 printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
478 if (ldap_modify_s(ld, group, mods))
480 for (idx_x500--; idx_x500 >= 0; idx_x500--)
481 Free(values_x500[idx_x500]);
482 ldap_uncache_entry(ld, group);
483 added_x500_entries = TRUE;
488 * If both counts were less than the maximum number we
489 * can handle at a time, then we are done.
491 if ((count_mail < MAX_VALUES) && (count_x500 < MAX_VALUES))
499 purge_group( char *group )
503 LDAPMod mod, *mods[2];
504 char dn[BUFSIZ], tmp[BUFSIZ], *values[2], **vp, **rdns;
507 if (debug & D_TRACE) {
509 printf("->purge_group(NULL)\n");
511 printf("->purge_group(%s)\n", group);
514 if (bind_status == UD_NOT_BOUND) {
515 if (auth((char *) NULL, 1) < 0)
519 * If the user did not supply us with a name, prompt them for
522 if ((group == NULL) || (*group == '\0')) {
523 printf("Group to purge? ");
525 fetch_buffer(tmp, sizeof(tmp), stdin);
530 sprintf(dn, "cn=%s, %s", group, group_base);
532 /* make sure the group in question exists */
533 if ((lm = find(group, FALSE)) == (LDAPMessage *) NULL) {
534 printf(" Could not locate group \"%s\"\n", group);
540 /* none of this stuff changes */
542 mods[1] = (LDAPMod *) NULL;
546 mod.mod_values = values;
547 mod.mod_type = "member";
548 mod.mod_op = LDAP_MOD_DELETE;
551 * Now cycle through all of the names in the "members" part of the
552 * group (but not the e-mail address part). Lookup each one, and
553 * if it isn't found, let the user know so s/he can delete it.
555 vp = Entry.attrs[attr_to_index("member")].values;
558 printf(" \"%s\" has no LDAP members. There is nothing to purge.\n", group);
561 for (; *vp != NULL; vp++) {
562 char ans[BUFSIZ], *ufn, *label = "Did not find: ";
563 int len = strlen(label);
568 ufn = my_ldap_dn2ufn(*vp);
569 format2(ufn, label, (char *) NULL, 2, 2 + len, col_size);
571 printf(" Purge, Keep, Replace, Abort [Keep]? ");
573 fetch_buffer(ans, sizeof(ans), stdin);
574 if ((ans[0] == '\0') || !strncasecmp(ans, "Keep", strlen(ans)))
576 if (!strncasecmp(ans, "Abort", strlen(ans))) {
577 ldap_uncache_entry(ld, dn);
580 if (!strncasecmp(ans, "Purge", strlen(ans)) || !strncasecmp(ans, "Replace", strlen(ans))) {
583 if (debug & D_GROUPS) {
584 register LDAPMod **lpp;
587 printf(" About to call ldap_modify_s()\n");
588 printf(" ld = 0x%x\n", ld);
589 printf(" dn = [%s]\n", Entry.DN);
590 for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
591 printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
592 printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
593 for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
594 printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
599 if (ldap_modify_s(ld, Entry.DN, mods))
602 /* now add the replacement if requested */
603 if (!strncasecmp(ans, "Purge", strlen(ans)))
605 rdns = ldap_explode_dn(*vp, TRUE);
606 if ((lm = find(*rdns, FALSE)) == NULL) {
607 printf(" Could not find a replacement for %s; purged only.\n", *rdns);
609 ldap_value_free(rdns);
612 values[0] = ldap_get_dn(ld, ldap_first_entry(ld, lm));
613 mod.mod_op = LDAP_MOD_ADD;
615 if (debug & D_GROUPS) {
616 register LDAPMod **lpp;
619 printf(" About to call ldap_modify_s()\n");
620 printf(" ld = 0x%x\n", ld);
621 printf(" dn = [%s]\n", Entry.DN);
622 for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
623 printf(" mods[%1d] code = %1d\n", i, (*lpp)->mod_op);
624 printf(" mods[%1d] type = %s\n", i, (*lpp)->mod_type);
625 for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
626 printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
631 if (ldap_modify_s(ld, Entry.DN, mods))
634 ldap_value_free(rdns);
636 /* set this back to DELETE for other purges */
637 mod.mod_op = LDAP_MOD_DELETE;
640 printf(" Did not recognize that answer.\n\n");
644 ldap_uncache_entry(ld, Entry.DN);
646 printf(" No entries were purged.\n");
658 static LDAPMod *mods[2] = { &mod, NULL };
659 static char *values[MAX_VALUES];
663 printf("->tidy()\n");
666 if (bind_status == UD_NOT_BOUND) {
667 if (auth((char *) NULL, 1) < 0) {
672 /* lookup the user, and see to which groups he has subscribed */
673 vp = ldap_explode_dn(bound_dn, TRUE);
674 if ((lm = find(*vp, TRUE)) == (LDAPMessage *) NULL) {
675 printf(" Could not locate \"%s\"\n", *vp);
682 vp = Entry.attrs[attr_to_index("memberOfGroup")].values;
684 printf(" You have not subscribed to any groups.\n");
688 /* now, loop through these groups, deleting the bogus */
689 for ( ; *vp != NULL; vp++) {
693 printf(" \"%s\" is not a valid group name.\n", *vp);
694 values[i++] = strdup(*vp);
695 if ( i >= MAX_VALUES ) {
696 printf( " At most %d invalid groups can be removed at one time; skipping the rest.\n", MAX_VALUES );
700 if (found_one == 0) {
702 printf(" You are not a member of any invalid groups. There is nothing to tidy.\n");
706 /* delete the most heinous entries */
708 mod.mod_values = values;
709 mod.mod_op = LDAP_MOD_DELETE;
710 mod.mod_type = "memberOfGroup";
711 if (ldap_modify_s(ld, bound_dn, mods))
713 ldap_uncache_entry(ld, bound_dn);
715 /* tidy up before we finish tidy_up */
722 * This routine is used to modify lists that can contain either Distinguished
723 * Names or e-mail addresses. This includes things like group members,
724 * the errors-to field in groups, and so on.
727 mod_addrDN( char *group, int offset )
729 char s[BUFSIZ], *new_value /* was member */, *values[2];
732 LDAPMod mod, *mods[2];
737 printf("->mod_addrDN(%s)\n", group);
740 * At this point the user can indicate that he wishes to add values
741 * to the attribute, delete values from the attribute, or replace the
742 * current list of values with a new list. The first two cases
743 * are very straight-forward, but the last case requires a little
744 * extra care and work.
749 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);
751 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);
754 /* initialize the modififier type */
759 printf(" Do you want to Add, Delete, or Replace? ");
761 printf(" Do you want to Add, Delete, Replace, or Bulk load? ");
763 fetch_buffer(s, sizeof(s), stdin);
768 if (!strncasecmp(s, "add", strlen(s))) {
769 mod.mod_op = LDAP_MOD_ADD;
772 else if (!strncasecmp(s, "delete", strlen(s))) {
773 mod.mod_op = LDAP_MOD_DELETE;
776 else if (!strncasecmp(s, "replace", strlen(s))) {
777 mod.mod_op = LDAP_MOD_REPLACE;
780 else if(!strncasecmp(s, "bulk", strlen(s))) {
787 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);
789 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);
792 if (mod.mod_op == LDAP_MOD_REPLACE) {
793 if ( verbose && !confirm_action( "The entire existing list will be overwritten with the new values you are about to enter." )) {
794 printf("\n Modification halted.\n");
800 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);
805 printf("%s? ", attrlist[offset].output_string);
807 fetch_buffer(s, sizeof(s), stdin);
812 * If the string the user has just typed has an @-sign in it,
813 * then we assume it is an e-mail address. In this case, we
814 * just store away whatever it is they have typed.
816 * If the string had no @-sign, then we look in the Directory,
817 * make sure it exists, and if it does, we add that.
819 * If the string begins with a comma, then strip off the
820 * comma, and pass it along to the LDAP server. This is
821 * the way one can force ud to accept a name. Handy for
822 * debugging purposes.
826 mod.mod_type = attrlist[offset].quipu_name;
828 else if (strchr(s, '@') == NULL) {
829 if ((mp = find(s, FALSE)) == (LDAPMessage *) NULL) {
830 printf(" Could not find \"%s\"\n", s);
831 if (verbose && (mod.mod_op == LDAP_MOD_DELETE)){
833 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);
839 new_value = Entry.DN;
840 mod.mod_type = attrlist[offset].quipu_name;
842 else if (mod.mod_op != LDAP_MOD_DELETE) {
844 * Don't screw around with what the user has typed
845 * if they are simply trying to delete a rfc822mailbox
848 * spaces on the left hand side of the e-mail
849 * address are bad news - we know that there
850 * must be a @-sign in the string, or else we
853 * note that this means a value like:
855 * first m. last@host.domain
857 * will be turned into:
859 * first.m..last@host.domain
861 * and the mailer will need to do the right thing
862 * with this; alternatively we could add code that
863 * collapsed multiple dots into a single dot
865 * Don't screw up things like:
867 * "Bryan Beecher" <bryan@umich.edu>
868 * Bryan Beecher <bryan@umich.edu>
871 if (strchr(s, '<') == NULL) {
872 for (cp = s; *cp != '@'; cp++)
877 strcpy(attrtype, "rfc822");
878 strcat(attrtype, attrlist[offset].quipu_name);
879 mod.mod_type = attrtype;
883 strcpy(attrtype, "rfc822");
884 strcat(attrtype, attrlist[offset].quipu_name);
885 mod.mod_type = attrtype;
888 /* fill in the rest of the ldap_mod() structure */
890 mods[1] = (LDAPMod *) NULL;
892 values[0] = new_value;
894 mod.mod_values = values;
897 if (debug & D_GROUPS) {
898 register LDAPMod **lpp;
901 printf(" About to call ldap_modify_s()\n");
902 printf(" ld = 0x%x\n", ld);
903 printf(" dn = [%s]\n", group);
904 for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
905 printf(" mods[%1d] code = %1d\n",
907 printf(" mods[%1d] type = %s\n",
908 i, (*lpp)->mod_type);
909 for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
910 printf(" mods[%1d] v[%1d] = %s\n",
916 if (my_ldap_modify_s(ld, group, mods)) {
918 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
919 if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE) {
920 printf(" Could not locate value \"%s\"\n",
929 ldap_uncache_entry(ld, group);
932 * If the operation was REPLACE, we now need to "zero out" the
933 * other "half" of the list (e.g., user specified an e-mail
934 * address; now we need to clear the DN part of the list).
936 * NOTE: WE HAVE ALREADY DONE HALF OF THE REPLACE ABOVE.
938 * Also, change the opcode to LDAP_MOD_ADD and give the user an
939 * opportunity to add additional members to the group. We
940 * only take this branch the very first time during a REPLACE
943 if (mod.mod_op == LDAP_MOD_REPLACE) {
944 if (!strncmp(mod.mod_type, "rfc822", 6))
945 mod.mod_type = mod.mod_type + 6;
947 strcpy(attrtype, "rfc822");
948 strcat(attrtype, mod.mod_type);
949 mod.mod_type = attrtype;
953 mod.mod_values = values;
954 mod.mod_op = LDAP_MOD_DELETE;
956 if (debug & D_GROUPS) {
957 register LDAPMod **lpp;
960 printf(" About to call ldap_modify_s()\n");
961 printf(" ld = 0x%x\n", ld);
962 printf(" dn = [%s]\n", group);
963 for (lpp = mods, i = 1; *lpp != NULL; lpp++, i++) {
964 printf(" mods[%1d] code = %1d\n",
966 printf(" mods[%1d] type = %s\n",
967 i, (*lpp)->mod_type);
968 for (cp = (*lpp)->mod_values, j = 1; *cp != NULL; cp++, j++)
969 printf(" mods[%1d] v[%1d] = %s\n", i, j, *cp);
973 if (my_ldap_modify_s(ld, group, mods)) {
975 * A "No such attribute" error is no big deal.
976 * We only wanted to clear the attribute anyhow.
979 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
980 if (ld_errno != LDAP_NO_SUCH_ATTRIBUTE) {
985 ldap_uncache_entry(ld, group);
987 printf(" \"%s\" has been added\n", new_value);
988 mod.mod_op = LDAP_MOD_ADD;
990 else if (verbose && (mod.mod_op == LDAP_MOD_ADD))
991 printf(" \"%s\" has been added\n", new_value);
992 else if (verbose && (mod.mod_op == LDAP_MOD_DELETE))
993 printf(" \"%s\" has been removed\n", new_value);
998 my_ldap_modify_s( LDAP *ldap, char *group, LDAPMod **mods )
1000 int was_rfc822member, rc;
1002 was_rfc822member = 0;
1004 if (!strcasecmp(mods[0]->mod_type, "rfc822member")) {
1005 mods[0]->mod_type = "mail";
1006 was_rfc822member = 1;
1009 rc = ldap_modify_s(ldap, group, mods);
1011 if (was_rfc822member)
1012 mods[0]->mod_type = "rfc822member";
1018 list_groups( char *who )
1021 char name[BUFSIZ], filter[BUFSIZ], *search_attrs[2];
1022 char *work_area[MAX_NUM_NAMES];
1028 if (debug & D_TRACE) {
1030 printf("->list_groups(NULL)\n");
1032 printf("->list_groups(%s)\n", who);
1036 * First, decide what entry we are going to list. If the
1037 * user has not included a name on the list command line,
1038 * we will use the person who was last looked up with a find
1041 * Once we know who to modify, be sure that they exist, and
1042 * parse out their DN.
1045 printf(" List groups belonging to whose entry? ");
1047 fetch_buffer(name, sizeof(name), stdin);
1048 if (name[0] != '\0')
1053 if ((mp = find(who, TRUE)) == NULL) {
1054 (void) ldap_msgfree(mp);
1055 printf(" Could not locate \"%s\" in the Directory.\n", who);
1058 dn = ldap_get_dn(ld, ldap_first_entry(ld, mp));
1060 rdns = ldap_explode_dn(dn, TRUE);
1062 printf("\n Listing groups belonging to \"%s\"\n", *rdns);
1064 /* lookup the groups belonging to this person */
1065 sprintf(filter, "owner=%s", dn);
1067 search_attrs[0] = "cn";
1068 search_attrs[1] = NULL;
1069 if ((rc = ldap_search_s(ld, UD_WHERE_ALL_GROUPS_LIVE, LDAP_SCOPE_SUBTREE,
1070 filter, search_attrs, FALSE, &mp)) != LDAP_SUCCESS &&
1071 rc != LDAP_SIZELIMIT_EXCEEDED && rc != LDAP_TIMELIMIT_EXCEEDED) {
1072 ldap_perror(ld, "ldap_search_s");
1073 ldap_value_free(rdns);
1076 if ((rc = ldap_count_entries(ld, mp)) < 0) {
1077 ldap_perror(ld, "ldap_count_entries");
1078 ldap_value_free(rdns);
1082 printf(" %s owns no groups in this portion of the Directory.\n", *rdns);
1083 ldap_value_free(rdns);
1087 printf(" %s owns %d groups.\n\n", *rdns, rc);
1088 print_list(mp, work_area, &rc);
1089 for (i = 1; work_area[i] != NULL; i++)
1092 ldap_value_free(rdns);
1097 bind_and_fetch( char *name )
1100 char tmp[MED_BUF_SIZE];
1103 if (debug & D_TRACE) {
1105 printf("->bind_and_fetch(NULL)\n");
1107 printf("->bind_and_fetch(%s)\n", name);
1110 if (bind_status == UD_NOT_BOUND) {
1111 if (auth((char *) NULL, 1) < 0)
1116 * If the user did not supply us with a name, prompt them for
1119 if ((name == NULL) || (*name == '\0')) {
1122 fetch_buffer(tmp, sizeof(tmp), stdin);
1127 /* remove quotes, dots, and underscores. */
1128 name = strip_ignore_chars(name);
1131 if (debug & D_GROUPS)
1132 printf("Group name = (%s)\n", name);
1135 /* make sure the group in question exists and is joinable */
1136 if ((lm = find(name, TRUE)) == (LDAPMessage *) NULL) {
1137 printf(" Could not locate group \"%s\"\n", name);
1144 if (debug & D_GROUPS)
1145 printf("Group DN = (%s)\n", Entry.DN);
1147 return(strdup(Entry.DN));
1151 list_memberships( char *who )
1154 char name[BUFSIZ], filter[BUFSIZ], *search_attrs[2];
1155 char *work_area[MAX_NUM_NAMES];
1161 if (debug & D_TRACE) {
1163 printf("->list_memberships(NULL)\n");
1165 printf("->list_memberships(%s)\n", who);
1169 * First, decide what entry we are going to list. If the
1170 * user has not included a name on the list command line,
1171 * we will use the person who was last looked up with a find
1174 * Once we know who to modify, be sure that they exist, and
1175 * parse out their DN.
1178 printf(" List memberships containing whose entry? ");
1180 fetch_buffer(name, sizeof(name), stdin);
1181 if (name[0] != '\0')
1186 if ((mp = find(who, TRUE)) == NULL) {
1187 (void) ldap_msgfree(mp);
1188 printf(" Could not locate \"%s\" in the Directory.\n", who);
1192 dn = ldap_get_dn(ld, ldap_first_entry(ld, mp));
1193 rdns = ldap_explode_dn(dn, TRUE);
1195 printf("\n Listing memberships of \"%s\"\n", *rdns);
1197 /* lookup the groups belonging to this person */
1198 sprintf(filter, "member=%s", dn);
1200 search_attrs[0] = "cn";
1201 search_attrs[1] = NULL;
1203 if ((rc = ldap_search_s(ld, UD_WHERE_ALL_GROUPS_LIVE, LDAP_SCOPE_SUBTREE,
1204 filter, search_attrs, FALSE, &mp)) != LDAP_SUCCESS &&
1205 rc != LDAP_SIZELIMIT_EXCEEDED && rc != LDAP_TIMELIMIT_EXCEEDED) {
1206 ldap_perror(ld, "ldap_search_s");
1208 ldap_value_free(rdns);
1211 if ((rc = ldap_count_entries(ld, mp)) < 0) {
1212 ldap_perror(ld, "ldap_count_entries");
1214 ldap_value_free(rdns);
1218 printf(" %s is not a member of any groups in this portion of the Directory.\n", *rdns);
1220 ldap_value_free(rdns);
1224 printf(" %s is a member of %d groups.\n\n", *rdns, rc);
1227 * print_list fills in the char * array starting at 1, not 0
1229 print_list(mp, work_area, &rc);
1230 for (i = 1; work_area[i] != NULL; i++)
1233 ldap_value_free(rdns);