Zap LDAPv2-only stuff

This commit is contained in:
Kurt Zeilenga 2002-08-08 03:01:14 +00:00
parent e69c9067c2
commit 9c28c9b361
38 changed files with 12 additions and 11925 deletions

View File

@ -4,6 +4,5 @@
##
## Clients Makefile.in for OpenLDAP
SUBDIRS = tools ud
CLEANDIRS = mail500 maildap
SUBDIRS = tools

View File

@ -1,31 +0,0 @@
# $OpenLDAP$
UNIX_PRGS = mail500
PROGRAMS = $(@PLAT@_PRGS)
SRCS= main.c
XSRCS= version.c
OBJS= main.o
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
XLIBS = $(LDAP_L)
XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
mail500 : version.o
$(LTLINK) -o $@ version.o $(OBJS) $(LIBS)
version.c: $(OBJS) $(XLIBS)
@-$(RM) $@
$(MKVERSION) mail500 > $@
install-local: $(PROGRAMS) FORCE
-$(MKDIR) $(DESTDIR)$(libexecdir)
@( \
for prg in $(PROGRAMS); do \
$(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \
$(DESTDIR)$(libexecdir); \
done \
)

View File

@ -1,186 +0,0 @@
This is the README file for mail500, a mailer that does directory
lookups via LDAP. The name is historical and refers to X.500.
If you are planning to run mail500 at your site, there are several
things you will have to tailor in main.c:
LDAPHOST - The host running an LDAP server
base[] - The array telling mail500 where/how to search for
things. See the explanation below.
*** WHAT mail500 DOES: ***
mail500 is designed to be invoked as a mailer (e.g., from sendmail),
similar to the way /bin/mail works. It takes a few required arguments
and then a list of addresses to deliver to. It expects to find the
message to deliver on its standard input. It looks up the addresses in
directory to figure out where to route the mail, and then execs sendmail
to do the actual delivery. It supports simple aliases, groups, and
mailing lists, the details of which are given below.
*** HOW IT WORKS (from the sendmail side): ***
The idea is that you might have a rule like this in your sendmail.cf
file somewhere in rule set 0:
R$*<@example.com>$* $#mail500$@example.com$:<$1>
This rule says that any address that ends in @example.com will cause the
mail500 mailer to be called to deliver the mail. You probably also want
to do something to prevent addresses like uuhost!user@example.com or
user%host@example.com from being passed to mail500. This can be done by
adding rules like this to rule set 9 where we strip off our local names:
R<@example.com>$*:$* $>10<@>$1:$2
R$+%$+<@example.com> $>10$1%$2<@>
R$+!$+<@example.com> $>10$1!$2<@>
See the sample sendmail.cf in this directory for more details.
For sendmail 8.9 (and later) users can use MAILER(mail500) if
mail500.m4 is placed within sendmail's cf/mailer directory.
The mail500 mailer should be defined similar to this in the
sendmail.cf file:
Mmail500, P=/usr/local/etc/mail500, F=DFMSmnXuh, A=mail500 -f $f -h $h -m $n@$w $u
This defines how mail500 will be treated by sendmail and what
arguments it will have when it's called. The various flags specified
by the F=... parameter are explained in your local sendmail book (with
any luck). The arguments to mail500 are as follows:
-f Who the mail is from. This will be used as the address
to which any errors should be sent (unless the address
specifies a mailing list - see below). Normally, sendmail
defines the $f macro to be the sender.
-h The domain for which the mail is destined. This is passed
in to mail500 via the $h macro, which is set by the
$@ metasymbol in the rule added to rule set 0 above.
It's normally used when searching for groups.
-m The mailer-daemon address. If errors have to be sent,
this is the address they will come from. $n is normally
set to mailer-daemon and $w is normally the local host
name.
The final argument $u is used to stand for the addresses to which to
deliver the mail.
*** HOW IT WORKS (from the mail500 side): ***
When mail500 gets invoked with one or more names to which to
deliver mail, it searches for each name in LDAP. Where it searches,
and what kind(s) of search(es) it does are compile-time configurable
by changing the base array in main.c. The configuration:
Base base[] =
{ "ou=People, dc=example, dc=com", 0
"uid=%s", "cn=%s", NULL,
"ou=System Groups, ou=Groups, dc=example, dc=com", 1
"(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
"ou=User Groups, ou=Groups, dc=example, dc=com", 1
"(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
NULL
};
means that in delivering mail to "name" mail500 would do the
the following searches, stopping if it found anything at any step:
Search (18) [2]: dc=com@dc=example@ou=People
Search subtree (uid=name)
Search (18) [3]: dc=com@dc=example@ou=People
Search subtree (cn=name)
Search (18) [4]: dc=com@dc=example@ou=Groups@ou=System Groups
Search subtree & ((cn=name)(associatedDomain=OpenLDAP.org))
Search (18) [5]: dc=com@dc=example@ou=Groups@ou=User Groups
Search subtree & ((cn=name)(associatedDomain=example.com))
Notice that when specifying a filter %s is replaced by the name,
or user portion of the address while %h is replaced by whatever is
passed in to mail500 via the -h option (typically the host portion
of the address).
You can also specify whether you want search results that matched
because the entry's RDN matched the search to be given preference
or not. We only give such preference in the mail group
portion of the searches. Beware with this option: the algorithm
used to decide whether an entry's RDN matched the search is very
simple-minded, and may not always be correct.
There is currently no limit on the number of areas searched (the base
array can be as large as you want), and an arbitrary limit of 2 filters
for each base. If you want more than that, simply changing the 3 in
the typedef for Base should do the trick.
*** HOW IT WORKS (from the LDAP side): ***
In LDAP, there are several new attribute types and one new object
class defined that mail500 makes use of. At its most basic, for normal
entries mail500 will deliver to the value(s) listed in the
rfc822Mailbox attribute of the entry. For example, an entry has
the attribute
mail: user@example.com
So mail sent to user@example.com will be delivered via mail500 to that
address. If there were multiple values for the mail attribute, multiple
copies of the mail would be sent.
A new object class, rfc822MailGroup, and several new attributes have
been defined to handle email groups/mailing lists. To use this, you
will need to add this to your local oidtable.oc:
# object class for representing RFC 822 mailgroups
rfc822MailGroup: umichObjectClass.2 : \
top : \
cn : \
rfc822Mailbox, member, memberOfGroup, owner, \
errorsTo, rfc822ErrorsTo, requestsTo, rfc822RequestsTo,
joinable, associatedDomain, \
description, multiLineDescription, \
userPassword, krbName, \
telecommunicationAttributeSet, postalAttributeSet
And you will need to add these to your local oidtable.at:
# attrs for rfc822mailgroups
multiLineDescription: umichAttributeType.2 : CaseIgnoreList
rfc822ErrorsTo: umichAttributeType.26 : CaseIgnoreIA5String
rfc822RequestsTo: umichAttributeType.27 : CaseIgnoreIA5String
joinable: umichAttributeType.28 : Boolean
memberOfGroup: umichAttributeType.29 : DN
errorsTo: umichAttributeType.30 : DN
requestsTo: umichAttributeType.31 : DN
The idea was to define a kind of hybrid mail group that could handle
people who were in LDAP or not. So, for example, members of a group
can be specified via the member attribute (for LDAP members) or the
rfc822MailBox attribute (for non-LDAP members). Similarly for the
errorsTo and rfc822ErrorsTo, and the requestsTo and rfc822RequestsTo
attributes.
To create a real mailing list, with a list maintainer, all you have to
do is create an rfc822MailGroup and fill in the errorsTo or
rfc822ErrorsTo attributes (or both). That will cause any errors
encountered when delivering mail to the group to go to the addresses
listed (or LDAP entry via it's mail attribute).
If you fill in the requestsTo or rfc822RequestsTo (or both) attributes,
mail sent to groupname-request will be sent to the addresses listed
there. mail500 does this automatically, so you don't have to explicitly
add the groupname-request alias to your group.
To allow users to join a group, there is the joinable flag. If TRUE,
mail500 will search for entries that have a memberOfGroup attribute
equal to the DN of the group, using the same algorithm it used to find
the group in the first place (i.e. the DNs and filters listed in the
base array). This allows people to join (or subscribe to) a group
without having to modify the group entry directly. If joinable is
FALSE, the search is not done.
Finally, keep in mind that this is somewhat experimental at the moment.
We are using it in production at U-M, but your mileage may vary...

View File

@ -1,51 +0,0 @@
PUSHDIVERT(-1)
## Copyright 1998-2002 The OpenLDAP Foundation, Redwood City, California, USA
## All rights reserved.
##
## Redistribution and use in source and binary forms are permitted only
## as authorized by the OpenLDAP Public License. A copy of this
## license is available at http://www.OpenLDAP.org/license.html or
## in file LICENSE in the top-level directory of the distribution.
POPDIVERT
dnl
dnl mail500 mailer
dnl
dnl This file should be placed in the sendmail's cf/mailer directory.
dnl To include this mailer in your .cf file, use the directive:
dnl MAILER(mail500)
dnl
ifdef(`MAIL500_HOST',
`define(`MAIL500_HOST_FLAG', `')',
`define(`MAIL500_HOST_FLAG', CONCAT(` -l ', CONCAT(MAIL500_HOST,` ')))')
ifdef(`MAIL500_MAILER_PATH',,
`ifdef(`MAIL500_PATH',
`define(`MAIL500_MAILER_PATH', MAIL500_PATH)',
`define(`MAIL500_MAILER_PATH', /usr/local/libexec/mail500)')')
ifdef(`MAIL500_MAILER_FLAGS',,
`define(`MAIL500_MAILER_FLAGS', `SmnXuh')')
ifdef(`MAIL500_MAILER_ARGS',,
`define(`MAIL500_MAILER_ARGS',
CONCAT(`mail500',CONCAT(MAIL500_HOST_FLAG,`-f $f -h $h -m $n@$w $u')))')
dnl
MAILER_DEFINITIONS
######################*****##############
### MAIL500 Mailer specification ###
##################*****##################
VERSIONID(`$OpenLDAP$')
Mmail500, P=MAIL500_MAILER_PATH, F=CONCAT(`DFM', MAIL500_MAILER_FLAGS), S=11/31, R=20/40, T=DNS/RFC822/X-Unix,
ifdef(`MAIL500_MAILER_MAX', `M=500_MAILER_MAX, ')A=MAIL500_MAILER_ARGS
LOCAL_CONFIG
# Mail500 Domains
#CQ foo.com
PUSHDIVERT(3)
# mail500 additions
R$* < @ $=Q > $* $#mail500 $@ $2 $: <$1> domain handled by mail500
POPDIVERT

File diff suppressed because it is too large Load Diff

View File

@ -1,208 +0,0 @@
#
# It's recommended use Sendmail's m4 configuration system to avoid
# mucking directly with .cf files
#
# Mostly rfc1123 compliant sendmail.cf
#
# Mail sendmail-admins-request@itd.umich.edu to join
# sendmail-admins@itd.umich.edu. sendmail-admins carries information
# regarding this sendmail.cf, including announcements of changes
# and discussions of interest to admins.
#
DWtotalrecall
Dw$W.rs.itd.umich.edu
DBcunyvm.cuny.edu
DUdestroyer.rs.itd.umich.edu
DV2.2
De$j sendmail ($v/$V) ready at $b
Dj$w
DlFrom $g $d
Dnmailer-daemon
Do.:%@!^=/[]
Dq$?x\"$x\" <$g>$|$g$.
OA/etc/aliases
OQ/var/spool/mqueue
OH/usr/lib/sendmail.hf
OS/usr/lib/sendmail.st
OP
OD
OX10
Ox5
Ou1
Og1
Odb
OF0600
OL9
Oo
Or15m
Os
OT3d
H?P?Return-Path: <$g>
HReceived: $?sfrom $s $.by $j ($v/$V)
$?rwith $r $.id $i; $b
H?D?Resent-Date: $a
H?F?Resent-From: $q
H?M?Resent-Message-Id: <$t.$i@$j>
H?M?Message-Id: <$t.$i@$j>
H?D?Date: $a
H?x?Full-Name: $x
H?F?From: $q
Troot uucp daemon
Pspecial-delivery=100
Pfirst-class=0
Pjunk=-100
# Organization:
#
# ruleset 3 and friends
# focus addresses, don't screw with them
# ruleset 0 and friends
# beat the hell out of addresses, convert them to
# their deliverable form
# mailers and associated rulesets
# * focused addresses are body addresses, and should be
# left as they are
# * unfocused addresses are envelope addresses, and should
# be converted to the mailers format
# ruleset 4
# remove focus on all addresses
# All addresses are passed through this rule. It functions by finding
# the host to delivery to, and marking it with <>
S3
R$*<$+>$* $2 remove comments
R$+:$*; $@ $1:$2; done if list
R$*@$+ $: $>5$1@$2 focus rfc822 addresses
R$+!$+ $: $>6$1!$2 focus uucp
R$*<@$+>$* $: $1<@$[$2$]>$3 canonicalize
R$*<$+>$* $@ $1<$2>$3 done if focused
R$+%$+ $: $1@$2 a%b -> a@b
R$+@$+%$+ $1%$2@$3 a@b%c -> a%b@c
R$+@$+ $: $>3$1@$2 try again...
# Find the "next hop" in normal rfc822 syntax. These rules
# all return upon marking the next hop with <>
S5
R@$+,@$+:$+ $@ <@$1>,@$2:$3 @a,@b:@c -> <@a>,@b:c
R@$+:$+ $@ <@$1>:$2 @a:b -> <@a>:b
R$+@$+ $@ $1<@$2> a@b -> a<@b>
# Focus bang style addresses. Won't change already focused addresses.
# Strips .uucp in bang paths, and converts domain syntax to rfc822 adresses.
S6
R$*<$+>$* $@ $1<$2>$3 already focused
R$+!$+ $: <$1!>$2 a!b -> <a!>b
R<$+.uucp!>$+ <$1!>$2 <a.uucp!>b -> <a!>b
# Find a mailer. This involves finding the "real" host to deliver to,
# by removing our local name, and/or doing a "domain forward"
S0
R$+ $: $>7$1 deliverable format
R$*<$+>$* $: $>11$1<$2>$3 domain forward
R<$+!>$+ $: $>12<$1!>$2 route uucp
R$*<@$+.bitnet>$* $#inet$@$B$:$1<@$2.bitnet>$3
R$*<@umich.edu>$* $#mail500$@umich.edu$:<$1>
R$*<@itd.umich.edu>$* $#mail500$@itd.umich.edu$:<$1>
#R<$+!>$+ $#uux$@$U$:<$1!>$2
R<$+!>$+ $#unet$@$U$:<$1!>$2
R$*<@$+>$* $#inet$@$2$:$1<@$2>$3
R$+ $#local$:$1
# Find the delivery address. Convert to standard-internal form,
# remove local name.
S7
R<$-.$+!>$+ $3<@$1.$2> <a.b!>c -> c<@a.b>
R$*<@$-.uucp>$* $>8$1@$2.uucp$3 *.uucp to !
R$*<$+>$* $: $>9$1<$2>$3 strip local name
# Convert rfc822 syntax to a uucp "bang path". This works well
# on normal a@b address and route-addrs. It will also do something
# to list syntax address, but it's not clear how correct it is.
S8
R@$+,@$+:$+ @$1!$2:$3 @a,@b:c -> @a!b:c
R@$+:$+@$+ $1!$3!$2 @a:b@c -> a!c!b
R@$+:$+!$+ $1!$2!$3 @a:b!c -> a!b!c
R$+@$+ $2!$1 a@b -> b!c
R$+ $: $>3$1 refocus
# Remove local names. You won't see things like a.b!u or u@b.uucp.
# Add new rules here to accept more than just the default locally.
S9
R$*<@$w>$* $>10$1<@>$2 remove local name
R<$W!>$+ $>10<!>$1
R<@umich.edu>$*:$* $>10<@>$1:$2
R$+%$+<@umich.edu> $>10$1%$2<@>
R$+!$+<@umich.edu> $>10$1!$2<@>
# Called only from above. Refocus and loop.
S10
R<@>,$+ $>3$1
R<@>:$+ $>3$1
R$+<@> $>3$1
R<!>$+ $>3$1
R$*<$+>$* $: $>7$1<$2>$3
# Convert domain names to uucp names, and refocus
S11
#R$*<@inquiry.org>$* $: $>8$1@inquiry$2
# Route uucp addresses, if we're not connected to them. We rely on the
# domain-path operator to down case addresses.
S12
R<$+!>$+ $: <${$1$}!>$2 pathalias route
R<$+!$+!>$+ <$1!>$2!$3 <a!b!>c -> <a!>b!c
Muux, P=/usr/bin/uux, F=DFMhu, S=13, R=14,
A=uux - -gC -b -r -a$f $h!rmail ($u)
Munet, P=[IPC], F=mDFMhuX, S=13, R=14, A=IPC $h, E=\r\n
Minet, P=[IPC], F=mDFMuX, S=15, R=15, A=IPC $h, E=\r\n
Mlocal, P=/bin/mail, F=rlsDFMmn, S=16, R=16, A=mail -d $u
Mprog, P=/bin/sh, F=lsDFMe, S=16, R=16, A=sh -c $u
Mmail500, P=/usr/local/etc/mail500, F=DFMSmnXuh,
A=mail500 -f $f -h $h -m $n@$w $u
# UUCP mailers require that the sender be in ! format.
# XXX Do we add our name to other people's paths?
S13
R$*<@$+>$* $: $>8$1@$2$3
#R<$w!>$+ $@ <$W!>$1
R<$+!>$+ $@ <$1!>$2
R$+:$*; $@ $1:$2;
R<> $@
#R$+ $@ <$W!>$1
R$+ $@ <$w!>$1
# Only add our name to local mail. Anything that's focused, leave alone.
S14
R$*<$+>$* $@ $1<$2>$3
R$+:$*; $@ $1:$2;
#R$+ $@ <$W!>$1
R$+ $@ <$w!>$1
# SMTP mailers require that addresses be in rfc822 format. If there's no
# @ in the address, add one.
S15
R<$W!>$+ $1<@$w>
R<$-.$+!>$+ $3<@$1.$2>
R$*<@$+>$* $@ $1<@$2>$3
R<$+!>$+ $@ $1!$2<@$w>
R$+:$*; $@ $1:$2;
R<> $@
R$+ $@ $1<@$w>
# Local and prog mailer
S16
R$+ $@ $1
#
# Called on all outgoing addresses. Used to remove the <> focus
#
S4
R$*<$+>$* $@ $1$2$3 defocus

View File

@ -1,31 +0,0 @@
# $OpenLDAP$
UNIX_PRGS = maildap
PROGRAMS = $(@PLAT@_PRGS)
SRCS= main.c
XSRCS= version.c
OBJS= main.o
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
XLIBS = $(LDAP_L)
XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
maildap : version.o
$(LTLINK) -o $@ version.o $(OBJS) $(LIBS)
version.c: $(OBJS) $(XLIBS)
@-$(RM) $@
$(MKVERSION) maildap > $@
install-local: $(PROGRAMS) FORCE
-$(MKDIR) $(DESTDIR)$(libexecdir)
@( \
for prg in $(PROGRAMS); do \
$(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \
$(DESTDIR)$(libexecdir); \
done \
)

View File

@ -1,357 +0,0 @@
*** WARNING: Preliminary ***
This is the README file for maildap, a mailer that does X.500 lookups
via LDAP. It is based on mail500.
If you are planning to run maildap at your site, you need to create a
configuration file. Previous versions required modifying the source
code for configuration. This is no longer necessary.
there are several
*** WHAT maildap DOES: ***
maildap is designed to be invoked as a mailer (e.g., from sendmail),
similar to the way /bin/mail works. It takes a few required arguments
and then a list of addresses to deliver to. It expects to find the
message to deliver on its standard input. It looks up the addresses in
X.500 to figure out where to route the mail, and then execs sendmail to
do the actual delivery. It supports simple aliases, groups, and
mailing lists, the details of which are given below.
*** HOW IT WORKS (from the sendmail side): ***
The idea is that you might have a rule like this in your sendmail.cf
file somewhere in rule set 0:
R$*<@umich.edu>$* $#maildap$@umich.edu$:<$1>
This rule says that any address that ends in @umich.edu will cause
the maildap mailer to be called to deliver the mail. You probably
also want to do something to prevent addresses like terminator!tim@umich.edu
or tim%terminator.rs.itd.umich.edu@umich.edu from being passed to maildap.
At U-M, we do this by adding rules like this to rule set 9 where we
strip off our local names:
R<@umich.edu>$*:$* $>10<@>$1:$2
R$+%$+<@umich.edu> $>10$1%$2<@>
R$+!$+<@umich.edu> $>10$1!$2<@>
You can also feed complete FQDN addresses to maildap. For instance,
you could define a class containing the list of domains you want to
serve like this:
FQ/etc/mail/maildapdomains
and then use a rule in rule set 0 like this:
R$*<$=Q>$* $#maildap $@$2 $:<$1@$2>
See the sample sendmail.cf in this directory for more details.
For sendmail 8.9 (and later) users can use MAILER(maildap) if
maildap.m4 is placed within sendmail's cf/mailer directory.
The maildap mailer should be defined similar to this in the
sendmail.cf file:
Mmaildap, P=/usr/local/etc/maildap, F=DFMSmnXuh, A=maildap -f $f -h $h -m $n@$w $u
This defines how maildap will be treated by sendmail and what
arguments it will have when it's called. The various flags specified
by the F=... parameter are explained in your local sendmail book (with
any luck). The arguments to maildap are as follows:
-f Who the mail is from. This will be used as the address
to which any errors should be sent (unless the address
specifies a mailing list - see below). Normally, sendmail
defines the $f macro to be the sender.
-h The domain for which the mail is destined. This is passed
in to maildap via the $h macro, which is set by the
$@ metasymbol in the rule added to rule set 0 above.
It's normally used when searching for groups.
-m The mailer-daemon address. If errors have to be sent,
this is the address they will come from. $n is normally
set to mailer-daemon and $w is normally the local host
name.
The final argument $u is used to stand for the addresses to which to
deliver the mail.
*** HOW IT WORKS (from the maildap side): ***
When maildap gets invoked with one or more names to which to deliver
mail, it searches for each name in X.500. Where it searches, and what
kind(s) of search(es) is controlled by a configuration file. There
are a number of different approaches to handling mail and no general
rules can be given. We will however present some examples of what you
can do. The new maildap is designed to be flexible and able to
accommodate most scenarios.
For instance, if you are following the mail distribution model that
the old maildap used, you need lines in the configuration file like
these:
search ldap:///ou=People, dc=OpenLDAP, dc=org??sub?\
(|(uid=%25l)(cn==%25l))
search ldap:///ou=System Groups, ou=Groups, dc=OpenLDAP, dc=org??sub?\
(&(cn=%25l)(associatedDomain==%25h))
search ldap:///ou=User Groups, ou=Groups, dc=OpenLDAP, dc=org??sub?\
(&(cn=%25l)(associatedDomain==%25h))
As you can see, searches are described by using LDAP URLs. You can
have as many searches as you want, but the first search that succeeds
completes the processing for a recipient address. You can provide an
attribute list in the URL and it will be honored. Otherwise, the
attribute list will default as explained below.
Filters can contain substitutions. Actually, they *should* contain
substitutions or the search result would not change with the recipient
address. Since the usual substitution character is % and it has
special meaning in URLs, you have to represent it according to the URL
syntax, that is, %25, 25 being the hex code of %. The filter can be
as complex as you want and you may make as many substitutions as you
want. Known substitutions at this time are:
%m The recipient address we are considering now, maybe fully
qualified
%h The host, that is, the value of the -h argument to
maildap
%l The local part from %m
%d The domain part from %m
So, in the above example, if the recipient address were
name@OpenLDAP.org, maildap would do the the following searches,
stopping if it found anything at any step:
Search (18) [2]: dc=org@dc=OpenLDAP@ou=People
Search subtree (uid=name)
Search (18) [3]: dc=org@dc=OpenLDAP@ou=People
Search subtree (cn=name)
Search (18) [4]: dc=org@dc=OpenLDAP@ou=Groups@ou=System Groups
Search subtree & ((cn=name)(associatedDomain=OpenLDAP.org))
Search (18) [5]: dc=org@dc=OpenLDAP@ou=Groups@ou=User Groups
Search subtree & ((cn=name)(associatedDomain=OpenLDAP.org))
[Beware: Currently unimplemented]
You can also specify whether you want search results that matched
because the entry's RDN matched the search to be given preference
or not. At U-M, we only give such preference in the mail group
portion of the searches. Beware with this option: the algorithm
used to decide whether an entry's RDN matched the search is very
simple-minded, and may not always be correct.
*** HOW IT WORKS (from the X.500 side): ***
First you need to decide what attributes you will search for and what
attributes will be used to deliver the message. In the classical
maildap, we would search by uid or cn and deliver to the mail
attribute. Another model is to search by the mail attribute and
deliver to something else, such as the uid if determined that the user
has a local account.
*** THE CONFIGURATION FILE
The configuration file is composed of lines that prescribe the
operation of maildap. Blank lines are ignored and lines beginning
with # are considered comments and ignored. Outside comments, the
sequence '\', newline, whitespace is ignored so that long lines can be
split for readability.
Attribute Definitions
Lines starting with 'attribute' define the semantics of an attribute.
Notice that attributes will be considered in the order they are
defined in the configuration file. This means that the presence of
some can preempt processing of other attributes and that attributes
that simply collect needed information must be defined before others
that use that information. The format is:
attribute name [multivalued] [final] [multiple-entries] [<syntax>] [<kind>]
If the attribute is "multivalued", all values will be considered. If
it is not and several values are found the entry is declared in error.
If the attribute is "final", its presence in an entry prevents further
analysis of the entry.
If the attribute is "multiple-entries" and it is of an appropriate
syntax that can point to other entries, all such entries are
considered, otherwise the entry is in error.
The known kinds are:
recipient The value(s) of this attribute should be
used as the address(es) to deliver the message
to if they are in an appropriate syntax. If
they otherwise point at other entries, they
should be retrieved and expanded as necessary
to complete the resolution of this entry. The
process is recursive and all.
errors The value(s) of this attribute represent the
entities that should receive error messages
for mail messages directed to this entry.
The presence of an attribute of this kind
force a change in the envelope sender address
of the message.
The known syntaxes are:
local-native-mailbox An unqualified mailbox name
rfc822 A fully qualified RFC822 mail address
rfc822-extended Currently identical to rfc822
dn The Distinguished Name of some other entry
url A URL either of the mailto: or ldap: styles,
others styles, notably file:, could be added.
No substitutions are supported currently.
search-with-filter=<filter> Do a search on all known search bases
with the give filter. The only currenty
substitution available is %D, the DN of the
current entry.
The default attributes to search
A line starting with "default-attributes" contains a comma-separated
list of attributes to use in searches everytime a specific list is not
known.
Search bases
As shown in the example above, lines starting with "search" provide
the search bases to use to initially try to resolve each entry or when
using attributes of syntax "search-with-filter".
*** EXAMPLES
A configuration file that approximates the operation of the old
maildap runs as follows:
attribute errorsTo errors dn
attribute rfc822ErrorsTo errors rfc822
attribute requestsTo request dn
attribute rfc822RequestsTo request rfc822
attribute owner owner dn
attribute mail multivalued recipient rfc822
attribute member multivalued recipient dn
attribute joinable multiple-entries recipient \
search-with-filter=(memberOfGroup=%D)
default-attributes objectClass,title,postaladdress,telephoneNumber,\
mail,description,owner,errorsTo,rfc822ErrorsTo,requestsTo,\
rfc822RequestsTo,joinable,cn,member,moderator,onVacation,uid,\
suppressNoEmailError
# Objectclasses that, when present, identify an entry as a group
group-classes mailGroup
search ldap:///ou=People, dc=OpenLDAP, dc=org??sub?\
(|(uid=%25l)(cn==%25l))
search ldap:///ou=System Groups, ou=Groups, dc=OpenLDAP, dc=org??sub?\
(&(cn=%25l)(associatedDomain==%25h))
search ldap:///ou=User Groups, ou=Groups, dc=OpenLDAP, dc=org??sub?\
(&(cn=%25l)(associatedDomain==%25h))
A configuration that approximates the semantics of the mailRecipient
and mailGroup classes used by Netscape:
attribute mgrpErrorsTo errors url
attribute rfc822ErrorsTo errors rfc822
attribute mailRoutingAddress final recipient rfc822
attribute mailHost final host forward-to-host
attribute uid final recipient local-native-mailbox
attribute uniqueMember multivalued recipient dn
attribute mgrpRFC822MailMember multivalued recipient rfc822-extended
attribute mgrpDeliverTo multivalued multiple-entries recipient url
default-attributes objetcClass,mailRoutingAddress,mailHost,uid,uniqueMember,\
mgrpRFC822MailMember,mgrpErrorsTo,rfc822ErrorsTo
# Objectclasses that, when present, identify an entry as a group
group-classes mailGroup
search ldap://localhost/dc=OpenLDAP,dc=org?\
objectClass,mailRoutingAddress,mailHost,uid?\
sub?\
(&(|(mail=%25m)(mailAlternateAddress=%25m))(objectClass=mailRecipient))
search ldap://localhost/dc=OpenLDAP,dc=org?\
objectClass,uniqueMember,mgrpRFC822MailMember,mgrpErrorsTo,mgrpDeliverTo,rfc822ErrorsTo?\
sub?\
(&(|(mail=%25m)(mailAlternateAddress=%25m))(objectClass=mailGroup))
[ The rest is from the original README and I did not rewrite it yet ]
In X.500, there are several new attribute types and one new object
class defined that maildap makes use of. At its most basic, for normal
entries maildap will deliver to the value(s) listed in the
rfc822Mailbox attribute of the entry. For example, at U-M my entry has
the attribute
mail= tim@terminator.rs.itd.umich.edu
So mail sent to tim@umich.edu will be delivered via maildap to that
address. If there were multiple values for the mail attribute, multiple
copies of the mail would be sent.
A new object class, rfc822MailGroup, and several new attributes have
been defined to handle email groups/mailing lists. To use this, you
will need to add this to your local oidtable.oc:
# object class for representing rfc 822 mailgroups
rfc822MailGroup: umichObjectClass.2 : \
top : \
cn : \
rfc822Mailbox, member, memberOfGroup, owner, \
errorsTo, rfc822ErrorsTo, requestsTo, rfc822RequestsTo,
joinable, associatedDomain, \
description, multiLineDescription, \
userPassword, krbName, \
telecommunicationAttributeSet, postalAttributeSet
And you will need to add these to your local oidtable.at:
# attrs for rfc822mailgroups
multiLineDescription: umichAttributeType.2 : CaseIgnoreList
rfc822ErrorsTo: umichAttributeType.26 : CaseIgnoreIA5String
rfc822RequestsTo: umichAttributeType.27 : CaseIgnoreIA5String
joinable: umichAttributeType.28 : Boolean
memberOfGroup: umichAttributeType.29 : DN
errorsTo: umichAttributeType.30 : DN
requestsTo: umichAttributeType.31 : DN
The idea was to define a kind of hybrid mail group that could handle
people who were in X.500 or not. So, for example, members of a group
can be specified via the member attribute (for X.500 members) or the
rfc822MailBox attribute (for non-X.500 members). Similarly for the
errorsTo and rfc822ErrorsTo, and the requestsTo and rfc822RequestsTo
attributes.
To create a real mailing list, with a list maintainer, all you have to
do is create an rfc822MailGroup and fill in the errorsTo or
rfc822ErrorsTo attributes (or both). That will cause any errors
encountered when delivering mail to the group to go to the addresses
listed (or X.500 entry via it's mail attribute).
If you fill in the requestsTo or rfc822RequestsTo (or both) attributes,
mail sent to groupname-request will be sent to the addresses listed
there. maildap does this automatically, so you don't have to explicitly
add the groupname-request alias to your group.
To allow users to join a group, there is the joinable flag. If TRUE,
maildap will search for entries that have a memberOfGroup attribute
equal to the DN of the group, using the same algorithm it used to find
the group in the first place (i.e. the DNs and filters listed in the
base array). This allows people to join (or subscribe to) a group
without having to modify the group entry directly. If joinable is
FALSE, the search is not done.
Finally, keep in mind that this is somewhat experimental at the moment.
We are using it in production at U-M, but your mileage may vary...

View File

@ -1,53 +0,0 @@
PUSHDIVERT(-1)
## Copyright 1998-2002 The OpenLDAP Foundation, Redwood City, California, USA
## All rights reserved.
##
## Redistribution and use in source and binary forms are permitted only
## as authorized by the OpenLDAP Public License. A copy of this
## license is available at http://www.OpenLDAP.org/license.html or
## in file LICENSE in the top-level directory of the distribution.
dnl
dnl maildap mailer
dnl
dnl This file should be placed in the sendmail's cf/mailer directory.
dnl To include this mailer in your .cf file, use the directive:
dnl MAILER(maildap)
dnl
ifdef(`MAILDAP_HOST',
`define(`MAILDAP_HOST_FLAG', CONCAT(` -l ', CONCAT(MAILDAP_HOST,` ')))',
`define(`MAILDAP_HOST_FLAG', `')')
ifdef(`MAILDAP_CONFIG_PATH',,
`define(`MAILDAP_CONFIG_PATH', /etc/mail/maildap.conf)')
ifdef(`MAILDAP_MAILER_PATH',,
`ifdef(`MAILDAP_PATH',
`define(`MAILDAP_MAILER_PATH', MAILDAP_PATH)',
`define(`MAILDAP_MAILER_PATH', /usr/local/libexec/maildap)')')
ifdef(`MAILDAP_MAILER_FLAGS',,
`define(`MAILDAP_MAILER_FLAGS', `SmnXuh')')
ifdef(`MAILDAP_MAILER_ARGS',,
`define(`MAILDAP_MAILER_ARGS',
CONCAT(`maildap',CONCAT(` -C ',MAILDAP_CONFIG_PATH,MAILDAP_HOST_FLAG,`-f $f -m $n@$w $u')))')
POPDIVERT
MAILER_DEFINITIONS
######################*****##############
### MAILDAP Mailer specification ###
##################*****##################
VERSIONID(`$OpenLDAP$')
Mmaildap, P=MAILDAP_MAILER_PATH, F=CONCAT(`DFM', MAILDAP_MAILER_FLAGS), S=11/31, R=20/40, T=DNS/RFC822/X-Unix,
ifdef(`MAILDAP_MAILER_MAX', `M=500_MAILER_MAX, ')A=MAILDAP_MAILER_ARGS
LOCAL_CONFIG
# Maildap Domains
#CQ foo.com
PUSHDIVERT(3)
# maildap additions
R$* < @ $=Q > $* $#maildap $@ $2 $: <$1@$2> domain handled by maildap
POPDIVERT

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +0,0 @@
# $OpenLDAP$
SRCS= main.c find.c mod.c print.c auth.c util.c help.c \
group.c edit.c globals.c
XSRCS= version.c
OBJS= main.o find.o mod.o print.o auth.o util.o help.o \
group.o globals.o edit.o
HDRS= ud.h
UNIX_PRGS = ud
PROGRAMS = $(@PLAT@_PRGS)
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
XLIBS = $(LDAP_L)
XXLIBS = $(TERMCAP_LIBS) $(SECURITY_LIBS) $(LDIF_LIBS) $(LUTIL_LIBS)
ud : version.o
$(LTLINK) -o $@ version.o $(OBJS) $(LIBS)
version.c: ${OBJS} $(XLIBS)
@-$(RM) $@
$(MKVERSION) -s -c -n Version UserDirectory > $@
install-local: FORCE
-$(MKDIR) $(DESTDIR)$(bindir)
-mv -f $(DESTDIR)$(bindir)/ud $(DESTDIR)$(bindir)/ud-
@( \
for prg in $(PROGRAMS); do \
$(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \
$(DESTDIR)$(bindir); \
done \
)

View File

@ -1,201 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 1991, 1992 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/stdlib.h>
#include <ac/ctype.h>
#include <ac/krb.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ac/unistd.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#include <ldap.h>
#include "ldap_defaults.h"
#include "ud.h"
static void set_bound_dn(char *s);
int
auth( char *who, int implicit )
{
int rc; /* return code from ldap_bind() */
char *passwd = NULL; /* returned by getpassphrase() */
char **rdns; /* for fiddling with the DN */
int authmethod;
int name_provided; /* was a name passed in? */
#ifdef HAVE_GETPWUID
struct passwd *pw; /* for getting user id */
#else
char *user;
#endif
char uidname[20];
LDAPMessage *mp; /* returned from find() */
static char prompt[MED_BUF_SIZE]; /* place for us to sprintf the prompt */
static char name[MED_BUF_SIZE]; /* place to store the user's name */
static char password[MED_BUF_SIZE]; /* password entered by user */
#ifdef DEBUG
if (debug & D_TRACE)
fprintf(stderr, "auth(%s, NULL)\n", who);
#endif
name_provided = ( who != NULL );
/*
* The user needs to bind. If <who> is not specified, we
* assume that authenticating as user id is what user wants.
*/
if (who == NULL && implicit) {
uidname[0] = '\0';
#ifdef HAVE_GETPWUID
if ((pw = getpwuid((uid_t)geteuid())) != (struct passwd *) NULL) {
sprintf(uidname, "uid=%s", pw->pw_name);
}
#else
user = getenv("USER");
if(user == NULL) user = getenv("USERNAME");
if(user == NULL) user = getenv("LOGNAME");
if(user != NULL) {
sprintf(uidname, "uid=%s", user);
}
#endif
if(uidname[0] != '\0') {
who = uidname;
}
}
if ( who == NULL ) {
if ( implicit )
printf( "You must first authenticate yourself to the Directory.\n" );
#ifdef UOFM
printf(" What is your name or uniqname? ");
#else
printf(" What is your name or user id? ");
#endif
fflush(stdout);
fetch_buffer(name, sizeof(name), stdin);
if (name[0] == '\0')
return( -1 );
who = name;
}
#ifdef DEBUG
if (debug & D_AUTHENTICAT)
printf(" Authenticating as \"%s\"\n", who);
#endif
/*
* Bail out if the name is bogus. If not, strip off the junk
* at the start of the DN, build a prompt, and get a password
* from the user. Then perform the ldap_bind().
*/
if ((mp = find(who, TRUE)) == NULL) {
printf(" I could not find \"%s\" in the Directory.\n", who);
printf(" I used a search base of ");
printbase("", search_base);
printf("\n");
#ifdef DEBUG
if (debug & D_AUTHENTICAT)
printf(" Could not find \"%s\"\n", who);
#endif
return(-1);
}
/*
* Fill in the Entry structure. May be handy later.
*/
(void) parse_answer(mp);
rdns = ldap_explode_dn(Entry.DN, TRUE);
printf(" Authenticating to the directory as \"%s\"...\n", *rdns );
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
if ( authmethod != LDAP_AUTH_KRBV4 )
#endif
{
authmethod = LDAP_AUTH_SIMPLE;
sprintf(prompt, " Enter your LDAP password: ");
do {
passwd = getpassphrase(prompt);
} while (passwd != NULL && *passwd == '\0');
if (passwd == NULL) {
(void) ldap_value_free(rdns);
return(0);
}
}
ldap_flush_cache( ld );
rc = ldap_bind_s(ld, Entry.DN, passwd, authmethod);
if (rc != LDAP_SUCCESS) {
int ld_errno;
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
fprintf(stderr, " Entry has no password\n");
else if (ld_errno == LDAP_INVALID_CREDENTIALS)
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
if ( authmethod == LDAP_AUTH_KRBV4 ) {
fprintf(stderr, " The Kerberos credentials are invalid.\n");
} else
#endif
{
fprintf(stderr, " The password you provided is incorrect.\n");
}
else
ldap_perror(ld, "ldap_bind_s" );
(void) ldap_bind_s(ld, default_bind_object,
(char *) NULL, LDAP_AUTH_SIMPLE);
if (default_bind_object == NULL)
set_bound_dn(NULL);
else
set_bound_dn(default_bind_object);
bind_status = UD_NOT_BOUND;
if (verbose)
printf(" Authentication failed.\n\n");
(void) ldap_value_free(rdns);
return(-1);
}
else if (verbose)
printf(" Authentication successful.\n\n");
else
printf("\n");
set_bound_dn(Entry.DN);
bind_status = UD_BOUND;
if (passwd != NULL)
(void) strcpy(password, passwd);
(void) ldap_value_free(rdns);
return(0);
}
static void
set_bound_dn( char *s )
{
if (bound_dn != NULL)
Free(bound_dn);
bound_dn = (s == NULL) ? NULL : strdup(s);
}

View File

@ -1,485 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 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 <sys/stat.h>
#include <ac/stdlib.h>
#include <ac/signal.h>
#include <ac/string.h>
#include <ac/ctype.h>
#include <ac/time.h>
#include <ac/wait.h>
#include <ac/unistd.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
#include <ldap.h>
#include "lutil.h"
#include "ldap_defaults.h"
#include "ud.h"
static int load_editor( void );
static int modifiable( char *s, short flag );
static int print_attrs_and_values( FILE *fp, struct attribute *attrs, short flag );
static int ovalues( char *attr );
static void write_entry( void );
static char entry_temp_file[L_tmpnam];
void
edit( char *who )
{
LDAPMessage *mp; /* returned from find() */
char *dn, **rdns; /* distinguished name */
char name[MED_BUF_SIZE]; /* entry to modify */
#ifdef DEBUG
if (debug & D_TRACE)
printf("->edit(%s)\n", who);
#endif
/*
* One must be bound in order to edit an entry.
*/
if (bind_status == UD_NOT_BOUND) {
if (auth((char *) NULL, 1) < 0)
return;
}
/*
* First, decide what entry we are going to modify. If the
* user has not included a name on the modify command line,
* we will use the person who was last looked up with a find
* command. If there is no value there either, we don't know
* who to modify.
*
* Once we know who to modify, be sure that they exist, and
* parse out their DN.
*/
if (who == NULL) {
if (verbose) {
printf(" Enter the name of the person or\n");
printf(" group whose entry you want to edit: ");
}
else
printf(" Edit 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));
rdns = ldap_explode_dn(dn, TRUE);
ldap_memfree(dn);
if (verbose) {
printf("\n Editing directory entry \"%s\"...\n", *rdns);
}
parse_answer(mp);
(void) ldap_msgfree(mp);
(void) ldap_value_free(rdns);
if (load_editor() < 0)
return;
write_entry();
(void) unlink(entry_temp_file);
ldap_uncache_entry(ld, Entry.DN);
return;
}
static int
load_editor( void )
{
FILE *fp;
char *cp, *editor = UD_DEFAULT_EDITOR;
#ifndef HAVE_SPAWNLP
int pid;
int status;
#endif
int rc;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->load_editor()\n");
#endif
strcpy(entry_temp_file, LDAP_TMPDIR LDAP_DIRSEP "udXXXXXX");
{
int tmpfd = mkstemp(entry_temp_file);
if( tmpfd < 0 ) {
perror("mkstemp");
return -1;
}
if ((fp = fdopen(tmpfd, "w")) == NULL) {
perror("fdopen");
return(-1);
}
}
fprintf(fp, "## Directory entry of %s\n", Entry.name);
fprintf(fp, "##\n");
fprintf(fp, "## Syntax is:\n");
fprintf(fp, "## <attribute-name>\n");
fprintf(fp, "## <TAB> <value 1>\n");
fprintf(fp, "## <TAB> : :\n");
fprintf(fp, "## <TAB> <value N>\n");
fprintf(fp, "## Lines beginning with a hash mark are comments.\n");
fprintf(fp, "##\n");
fflush(fp);
if (isgroup())
rc = print_attrs_and_values(fp, Entry.attrs, ATTR_FLAG_GROUP_MOD);
else
rc = print_attrs_and_values(fp, Entry.attrs, ATTR_FLAG_PERSON_MOD);
fclose(fp);
if ( rc != 0 ) {
(void) unlink(entry_temp_file);
return( rc );
}
/* edit the temp file with the editor of choice */
if ((cp = getenv("EDITOR")) != NULL)
editor = cp;
if (verbose) {
char *p;
if (( p = strrchr( editor, *LDAP_DIRSEP )) == NULL ) {
p = editor;
} else {
++p;
}
printf(" Using %s as the editor...\n", p );
#ifndef HAVE_SPAWNLP
sleep(2);
#endif
}
#ifdef HAVE_SPAWNLP
rc = _spawnlp( _P_WAIT, editor, editor, entry_temp_file, NULL );
if(rc != 0) {
fatal("spawnlp");
}
#else
if ((pid = fork()) == 0) {
/* child - edit the Directory entry */
(void) SIGNAL(SIGINT, SIG_IGN);
(void) execlp(editor, editor, entry_temp_file, NULL);
/*NOTREACHED*/
(void) fatal(editor);
}
else if (pid > 0) {
/* parent - wait until the child proc is done editing */
RETSIGTYPE (*handler)();
handler = SIGNAL(SIGINT, SIG_IGN);
(void) wait(&status);
(void) SIGNAL(SIGINT, handler);
}
else {
fatal("fork");
/*NOTREACHED*/
}
#endif
return(0);
}
static int
print_attrs_and_values( FILE *fp, struct attribute *attrs, short int flag )
{
register int i, j;
for (i = 0; attrs[i].quipu_name != NULL; i++) {
if (!modifiable(attrs[i].quipu_name,
(short) (flag|ATTR_FLAG_MAY_EDIT)))
{
continue;
}
fprintf(fp, "%s\n", attrs[i].quipu_name);
if ( attrs[i].number_of_values > MAX_VALUES ) {
printf(" The %s attribute has more than %d values.\n",
attrs[i].quipu_name, MAX_VALUES );
printf(" You cannot use the vedit command on this entry. Sorry!\n" );
return( -1 );
}
for (j = 0; j < attrs[i].number_of_values; j++)
fprintf(fp, "\t%s\n", attrs[i].values[j]);
}
return( 0 );
}
static int
modifiable( char *s, short int flag )
{
register int i;
for (i = 0; attrlist[i].quipu_name != NULL; i++) {
if (strcasecmp(s, attrlist[i].quipu_name))
continue;
if ((attrlist[i].flags & flag) == ATTR_FLAG_NONE)
return(FALSE);
return(TRUE);
}
/* should never be here */
return(FALSE);
}
static void
write_entry( void )
{
int i = 0, j, number_of_values = -1;
FILE *fp;
char *cp, line[LARGE_BUF_SIZE], *values[MAX_VALUES], **vp;
LDAPMod *mods[MAX_ATTRS + 1];
LDAPMod *modp = NULL;
/* parse the file and write the values to the Directory */
if ((fp = fopen(entry_temp_file, "r")) == NULL) {
perror("fopen");
return;
}
for (;;) {
(void) fgets(line, sizeof(line), fp);
if (feof(fp))
break;
line[strlen(line) - 1] = '\0'; /* kill newline */
cp = line;
if (*cp == '#')
continue;
if (isspace((unsigned char)*cp)) { /* value */
while (isspace((unsigned char)*cp))
cp++;
values[number_of_values++] = strdup(cp);
if ( number_of_values >= MAX_VALUES ) {
printf(" A maximum of %d values can be handled at one time. Sorry!\n", MAX_VALUES );
return;
}
continue;
}
/* attribute */
while (isspace((unsigned char)*cp))
cp++;
/*
* If the number of values is greater than zero, then we
* know that this is not the first time through this
* loop, and we also know that we have a little bit
* of work to do:
*
* o The modify operation needs to be changed from
* a DELETE to a REPLACE
*
* o The list of values pointer needs to be changed
* from NULL, to a NULL-terminated list of char
* pointers.
*/
if (number_of_values > 0) {
modp->mod_op = LDAP_MOD_REPLACE;
if ((vp = (char **) Malloc(sizeof(char *) * (number_of_values + 2))) == (char **) NULL) {
fatal("Malloc");
/*NOTREACHED*/
}
modp->mod_values = vp;
for (j = 0; j < number_of_values; j++) {
*vp++ = strdup(values[j]);
(void) Free(values[j]);
}
*vp = NULL;
}
/*
* If there are no values, and there were no values to begin
* with, then there is nothing to do.
*/
if ((number_of_values == 0) && (ovalues(modp->mod_type) == 0)) {
#ifdef DEBUG
if (debug & D_MODIFY)
printf(" %s has zero values - skipping\n",
modp->mod_type);
#endif
(void) Free(modp->mod_type);
modp->mod_type = strdup(cp);
modp->mod_op = LDAP_MOD_DELETE;
modp->mod_values = NULL;
continue;
}
/*
* Fetch a new modify structure.
*
* Assume a DELETE operation with no values.
*/
if ((modp = (LDAPMod *) Malloc(sizeof(LDAPMod))) == NULL) {
fatal("Malloc");
/*NOTREACHED*/
}
modp->mod_values = NULL;
modp->mod_type = strdup(cp);
modp->mod_op = LDAP_MOD_DELETE;
mods[i++] = modp;
number_of_values = 0;
}
fclose(fp);
/* check the last one too */
if (number_of_values > 0) {
modp->mod_op = LDAP_MOD_REPLACE;
/*
* Fetch some value pointers.
*
* number_of_values To store the values
* 1 For the NULL terminator
* 1 In case we need it to store
* the RDN as on of the values
* of 'cn' in case it isn't there
*/
if ((vp = (char **) Malloc(sizeof(char *) * (number_of_values +
2))) == (char **) NULL) {
fatal("Malloc");
/*NOTREACHED*/
}
modp->mod_values = vp;
for (j = 0; j < number_of_values; j++) {
*vp++ = strdup(values[j]);
(void) Free(values[j]);
}
*vp = NULL;
}
else if ((number_of_values == 0) &&
(ovalues(mods[i - 1]->mod_type) == 0)) {
#ifdef DEBUG
if (debug & D_MODIFY)
printf(" %s has zero values - skipping\n",
mods[i - 1]->mod_type);
#endif
Free(mods[i - 1]->mod_type);
Free(mods[i - 1]);
i--;
}
mods[i] = (LDAPMod *) NULL;
/*
* If one of the mods pointers is 'cn', be sure that the RDN is one
* of the values.
*/
for (j = 0; j < i; j++) {
if (strcasecmp("cn", mods[j]->mod_type))
continue;
/*
* True only if there WERE values, but the person deleted
* them all.
*/
if (mods[j]->mod_values == NULL) {
mods[j]->mod_op = LDAP_MOD_REPLACE;
if ((vp = (char **) Malloc(sizeof(char *) * 2)) == (char **) NULL) {
fatal("Malloc");
/*NOTREACHED*/
}
mods[j]->mod_values = vp;
*vp++ = strdup(Entry.name);
*vp = NULL;
break;
}
/*
* Be sure that one of the values of 'cn' is the RDN.
*/
for (vp = mods[j]->mod_values; *vp != NULL; vp++) {
if (strcasecmp(*vp, Entry.DN))
continue;
break;
}
if (*vp == NULL) {
*vp++ = strdup(Entry.name);
*vp = NULL;
break;
}
}
#ifdef DEBUG
if (debug & D_MODIFY) {
register int x, y;
printf(" ld = 0x%x\n", ld);
printf(" dn = [%s]\n", Entry.DN);
for (x = 0; mods[x] != (LDAPMod *) NULL; x++) {
printf(" mods[%d]->mod_op = %s\n",
x, code_to_str(mods[x]->mod_op));
printf(" mods[%d]->mod_type = %s\n",
x, mods[x]->mod_type);
if (mods[x]->mod_values == NULL)
printf(" mods[%d]->mod_values = NULL\n", x);
else {
for (y = 0; mods[x]->mod_values[y] != NULL; y++)
printf(" mods[%d]->mod_values[%1d] = %s\n",
x, y, mods[x]->mod_values[y]);
printf(" mods[%d]->mod_values[%1d] = NULL\n",
x, y);
}
printf("\n");
}
}
#endif
if (ldap_modify_s(ld, Entry.DN, mods))
mod_perror(ld);
else
printf(" Modification complete.\n" );
/* clean up */
for (i = 0; mods[i] != NULL; i++)
free_mod_struct(mods[i]);
return;
}
static int
ovalues( char *attr )
{
struct attribute *ap;
/*
* Lookup the attribute with quipu_name 'attr' in the Entry
* structure and return the number of values.
*/
for (ap = Entry.attrs; ap->quipu_name != NULL; ap++) {
if (!strcasecmp(ap->quipu_name, attr))
return(ap->number_of_values);
}
/* should never get to this point unless 'attr' was something odd */
return(0);
}

View File

@ -1,2 +0,0 @@
server <your ldap server host name here>
base <your X.500 default search base here>

View File

@ -1,456 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 1991, 1992, 1993
* 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/stdlib.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ldap.h>
#include "ud.h"
static int num_picked = 0; /* used when user picks entry at More prompt */
int
vrfy( char *dn )
{
LDAPMessage *results = NULL;
static char *attrs[2] = { "1.1", NULL };
int ld_errno = 0;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->vrfy(%s)\n", dn);
#endif
/* verify that this DN exists in the directory */
(void) ldap_search_s(ld, dn, LDAP_SCOPE_BASE, NULL, attrs, TRUE, &results);
(void) ldap_msgfree(results);
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
if ((ld_errno == LDAP_NO_SUCH_OBJECT) || (ld_errno == LDAP_INVALID_DN_SYNTAX))
return(0);
else if (ld_errno == LDAP_SUCCESS)
return(1);
else {
ldap_perror(ld, "ldap_search");
return(0);
}
}
static LDAPMessage *
disambiguate( LDAPMessage *result, int matches, char **read_attrs, char *who )
{
int choice; /* entry that user chooses */
int i;
char *namelist[MAX_NUM_NAMES]; /* names found */
char response[SMALL_BUF_SIZE]; /* results from user */
char *name = NULL; /* DN to lookup */
LDAPMessage *mp = NULL;
int ld_errno = 0;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->disambiguate(%x, %d, %x, %s)\n", result, matches,
read_attrs, who);
#endif
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
/*
* If we are here, it means that we got back multiple answers.
*/
if ((ld_errno == LDAP_TIMELIMIT_EXCEEDED)
|| (ld_errno == LDAP_SIZELIMIT_EXCEEDED)) {
if (verbose) {
printf(" Your query was too general and a limit was exceeded. The results listed\n");
printf(" are not complete. You may want to try again with a more refined query.\n\n");
}
else
printf(" Time or size limit exceeded. Partial results follow.\n\n");
}
printf(" %1d names matched \"%s\".\n", matches, who);
for (;;) {
printf(" Do you wish to see a list of names? ");
fflush(stdout);
(void) memset(response, '\0', sizeof(response));
fetch_buffer(response, sizeof(response), stdin);
switch (response[0]) {
case 'n' :
case 'N' :
case '\0' :
case '\n' :
return(NULL);
/* NOTREACHED */
case 'y' :
case 'Y' :
print_list(result, namelist, &matches);
if (num_picked == 0)
choice = pick_one(matches);
else
choice = num_picked;
num_picked = 0;
if (choice >= 0)
name = strdup(namelist[choice]);
/*
* Now free up all of the pointers allocated in
* namelist. The print_list() routine that filled
* in this collection of strings starts at 1, not 0.
*/
for (i = 1; namelist[i] != NULL; i++)
Free(namelist[i]);
if (choice < 0) {
if (name != NULL)
Free(name);
return(NULL);
}
#ifdef DEBUG
if (debug & D_FIND) {
printf(" Calling ldap_search_s()\n");
printf(" ld = 0x%x\n", ld);
printf(" search base = %s\n", name);
printf(" scope = LDAP_SCOPE_BASE\n");
printf(" filter = (objectClass=*)\n");
for (i = 0; read_attrs[i] != NULL; i++)
printf(" read_attrs[%d] = %s\n", i, read_attrs[i]);
printf(" read_attrs[%d] = NULL\n", i);
printf(" attrsonly = FALSE\n");
printf(" &mp = 0x%x\n", &mp);
}
#endif
if (ldap_search_s(ld, name, LDAP_SCOPE_BASE, NULL, read_attrs, FALSE, &mp) != LDAP_SUCCESS) {
ldap_perror(ld, "ldap_search_s");
Free(name);
ldap_msgfree(mp);
return(NULL);
}
Free(name);
return(mp);
/* NOTREACHED */
default :
printf(" Please enter 'y', 'n', or RETURN.\n");
break;
}
}
}
LDAPMessage *
find( char *who, int quiet )
{
register int i, j, k; /* general ints */
int matches; /* from ldap_count_entries() */
int admonished = FALSE;
static int attrs_set = 0;
static char *read_attrs[MAX_ATTRS]; /* attrs to use in a read op */
static char *search_attrs[MAX_ATTRS]; /* attrs to use in a srch op */
static int rc; /* return from ldap_search */
LDAPMessage *ldtmp, *res; /* results returned from search */
char name[MED_BUF_SIZE];
char response[SMALL_BUF_SIZE];
char *cp, *dn, **rdns;
LDAPFiltInfo *fi;
#ifdef DEBUG
if (debug & D_TRACE)
fprintf(stderr, "->find(%s)\n", who);
#endif
/* did not specify a 'who' */
if (who == NULL) {
printf(" Locate whose entry? ");
fflush(stdout);
fetch_buffer(name, sizeof(name), stdin);
if (name[0] != '\0')
who = name;
else
return(NULL);
}
if (attrs_set == 0) {
j = k = 0;
attrs_set = 1;
for (i = 0; attrlist[i].quipu_name != NULL; i++) {
if (attrlist[i].flags & ATTR_FLAG_READ)
read_attrs[j++] = attrlist[i].quipu_name;
if (attrlist[i].flags & ATTR_FLAG_SEARCH)
search_attrs[k++] = attrlist[i].quipu_name;
}
read_attrs[j] = NULL;
search_attrs[k] = NULL;
}
/*
* Old users of the MTS *USERDIRECTORY will likely wrap the name
* in quotes. Not only is this unnecessary, but it also won't work.
*/
for (cp = strchr(who, '"'); cp != NULL; cp = strchr(cp, '"')) {
if (!admonished) {
printf(" You do not need to enclose names in quotes.\n");
admonished = TRUE;
}
*cp++ = ' ';
if (*cp == '\0')
break;
}
for (fi = ldap_getfirstfilter(lfdp, "ud", who); fi != NULL;
fi = ldap_getnextfilter(lfdp)) {
#ifdef DEBUG
if (debug & D_FIND)
printf("Searching, filter = %s\n", fi->lfi_filter);
#endif
if ((rc = ldap_search_s(ld, search_base, fi->lfi_scope,
fi->lfi_filter, search_attrs, FALSE, &res)) != LDAP_SUCCESS &&
rc != LDAP_SIZELIMIT_EXCEEDED && rc != LDAP_TIMELIMIT_EXCEEDED) {
ldap_perror(ld, "ldap_search_s");
ldap_msgfree(res);
return(NULL);
}
if ((matches = ldap_count_entries(ld, res)) < 0) {
ldap_perror(ld, "ldap_count_entries");
ldap_msgfree(res);
return(NULL);
}
else if (matches == 1) {
dn = ldap_get_dn(ld, ldap_first_entry(ld, res));
ldap_msgfree(res);
if (!quiet)
printf(" Found one %s match for \"%s\"\n",
fi->lfi_desc, who);
if (!fi->lfi_isexact) {
rdns = ldap_explode_dn(dn, TRUE);
printf(" Do you mean %s? ", *rdns);
(void) ldap_value_free(rdns);
fflush(stdout);
fetch_buffer(response, sizeof(response), stdin);
if ((response[0] == 'n') || (response[0] == 'N'))
{
ldap_memfree(dn);
return(NULL);
}
}
#ifdef DEBUG
if (debug & D_FIND) {
printf(" Calling ldap_search_s()\n");
printf(" ld = 0x%x\n", ld);
printf(" dn = %s\n", dn);
printf(" scope = LDAP_SCOPE_BASE\n");
printf(" filter = %s\n", "(objectClass=*)");
for (i = 0; read_attrs[i] != NULL; i++)
printf(" read_attrs[%d] = %s\n", i, read_attrs[i]);
printf(" read_attrs[%d] = NULL\n", i);
printf(" attrsonly = FALSE\n");
printf(" &results = 0x%x\n", &res);
}
#endif
if (ldap_search_s(ld, dn, LDAP_SCOPE_BASE, NULL, read_attrs, FALSE, &res) != LDAP_SUCCESS) {
ldap_perror(ld, "ldap_search_s");
ldap_msgfree(res);
res = NULL;
}
ldap_memfree(dn);
return(res);
}
else if (matches > 0) {
ldtmp = disambiguate(res, matches, read_attrs, who);
ldap_msgfree(res);
return(ldtmp);
}
/* if we're here, there were zero matches */
ldap_msgfree(res);
}
return(NULL);
}
int
pick_one( int i )
{
int n;
char user_pick[SMALL_BUF_SIZE];
#ifdef DEBUG
if (debug & D_TRACE)
printf("->pick_one(%d)\n", i);
#endif
/* make the user pick an entry */
for (;;) {
printf(" Enter the number of the name you want or Q to quit: ");
fflush(stdout);
fetch_buffer(user_pick, sizeof(user_pick), stdin);
if (user_pick[0] == 'q' || user_pick[0] == 'Q')
return(-1);
n = atoi(user_pick);
if ((n > 0) && (n <= i))
return(n);
printf(" Invalid response\n");
}
/* NOTREACHED */
}
void
print_list( LDAPMessage *list, char **names, int *matches )
{
char **rdns, **cpp;
char resp[SMALL_BUF_SIZE];
register LDAPMessage *ep;
register int i = 1;
register int rest = 4; /* 4, not 1 */
#ifdef DEBUG
if (debug & D_TRACE)
printf("->print_list(%x, %x, %x)\n", list, names, matches);
#endif
/* print a list of names from which the user will select */
for (ep = ldap_first_entry(ld, list); ep != NULL; ep = ldap_next_entry(ld, ep)) {
names[i] = ldap_get_dn(ld, ep);
rdns = ldap_explode_dn(names[i], TRUE);
cpp = ldap_get_values(ld, ep, "title");
if (cpp == NULL)
printf(" %3d. %s\n", i, *rdns);
else
printf(" %3d. %s, %s\n", i, *rdns, *cpp);
ldap_value_free(rdns);
ldap_value_free(cpp);
i++;
if ((rest++ > (lpp - 1)) && (i < *matches)) {
again:
printf(" More? ");
fflush(stdout);
fetch_buffer(resp, sizeof(resp), stdin);
if ((resp[0] == 'n') || (resp[0] == 'N'))
break;
else if ((num_picked = atoi(resp)) != 0) {
if (num_picked < i)
break;
else
goto again;
}
rest = 1;
}
}
*matches = i - 1;
names[i] = NULL;
return;
}
int
find_all_subscribers( char **sub, char *group )
{
int count;
LDAPMessage *result;
static char *attributes[] = { "cn", NULL };
char filter[MED_BUF_SIZE];
register LDAPMessage *ep;
register int i = 0;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->find_all_subscribers(%x, %s)\n", sub, group);
#endif
sprintf(filter, "%s=%s", "memberOfGroup", group);
if (ldap_search_s(ld, search_base, LDAP_SCOPE_SUBTREE, filter, attributes, FALSE, &result) != LDAP_SUCCESS) {
int ld_errno = 0;
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
return(0);
ldap_perror(ld, "ldap_search_s");
return(0);
}
count = ldap_count_entries(ld, result);
if (count < 1) {
ldap_msgfree(result);
return(0);
}
if ( count > MAX_VALUES ) {
printf( " Only retrieving the first %d subscribers....\n",
MAX_VALUES );
}
for (ep = ldap_first_entry(ld, result); i < MAX_VALUES && ep != NULL; ep = ldap_next_entry(ld, ep)) {
sub[i++] = ldap_get_dn(ld, ep);
#ifdef DEBUG
if (debug & D_PARSE)
printf("sub[%d] = %s\n", i - 1, sub[i - 1]);
#endif
}
sub[i] = NULL;
ldap_msgfree(result);
return(count);
}
char *
fetch_boolean_value( char *who, struct attribute attr )
{
LDAPMessage *result; /* from the search below */
register LDAPMessage *ep; /* entry pointer */
register char **vp; /* for parsing the result */
static char *attributes[] = { NULL, NULL };
#ifdef DEBUG
if (debug & D_TRACE)
printf("->fetch_boolean_value(%s, %s)\n", who, attr.quipu_name);
#endif
attributes[0] = attr.quipu_name;
if (ldap_search_s(ld, who, LDAP_SCOPE_BASE, NULL, attributes, FALSE, &result) != LDAP_SUCCESS) {
int ld_errno = 0;
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
return("FALSE");
ldap_perror(ld, "ldap_search_s");
ldap_msgfree(result);
return(NULL);
}
/*
* We did a read on one name and only asked for one attribute.
* There's no reason to loop through any of these structures.
*
* If ldap_first_attribute() returns NULL, then this entry did
* not have this particular attribute.
*/
ep = ldap_first_entry(ld, result);
if ((vp = (char **) ldap_get_values(ld, ep, attr.quipu_name)) == NULL) {
ldap_msgfree(result);
return("FALSE");
}
else {
ldap_msgfree(result);
if (!strcasecmp(*vp, "TRUE")) {
ldap_value_free(vp);
return("TRUE");
}
else if (!strcasecmp(*vp, "FALSE")) {
ldap_value_free(vp);
return("FALSE");
}
else {
fprintf(stderr, " Got garbage -> [%s]\n", *vp);
ldap_value_free(vp);
return(NULL);
}
}
}

View File

@ -1,77 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 1992, 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/time.h> /* ldap.h needs time_t */
#include <ldap.h>
#include "ud.h"
struct attribute attrlist[] = {
/*
* Field 1 = Quipu name
* Field 2 = String used when printing the field
* Field 3 = function used to modify this field (if any)
* Field 4 = Flags specifying how this field is displayed
*/
{ "memberOfGroup", "Subscriptions", 0, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DN },
{ "acl", "Access Control", 0, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ },
{ "cn", "Aliases", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_SEARCH | ATTR_FLAG_GROUP_MOD },
{ "title", "Title", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_SEARCH | ATTR_FLAG_PERSON_MOD },
{ "postalAddress", "Business address", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_GROUP_MOD | ATTR_FLAG_IS_MULTILINE },
{ "telephoneNumber", "Business phone", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_GROUP_MOD },
{ "mail", "E-mail address", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_SEARCH | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_MAY_EDIT },
{ "member", "Members", mod_addrDN, ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DN | ATTR_FLAG_GROUP_MOD },
{ "homePhone", "Home phone", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD },
{ "homePostalAddress", "Home address", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_IS_MULTILINE },
{ "objectClass", "Object class", 0, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_SEARCH },
#ifdef UOFM
{ "multiLineDescription", "Description", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_GROUP_MOD | ATTR_FLAG_IS_MULTILINE },
#endif
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
{ "krbName", "Kerberos name", 0, ATTR_FLAG_PERSON | ATTR_FLAG_READ },
#endif
{ "description", "Brief description", 0, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ },
{ "facsimileTelephoneNumber", "Fax number", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_GROUP_MOD },
{ "pager", "Pager number", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD },
{ "uid", "Uniqname", 0, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ },
{ "userPassword", "Password", 0, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ },
#ifdef UOFM
{ "noBatchUpdates", "No batch updates", set_updates, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD },
#endif
{ "joinable", "Joinable flag", set_boolean, ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_GROUP_MOD },
{ "associatedDomain", "Associated domain", change_field, ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_GROUP_MOD },
{ "owner", "Owner", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DN | ATTR_FLAG_GROUP_MOD },
{ "rfc822ErrorsTo", "Errors to", change_field, ATTR_FLAG_GROUP | ATTR_FLAG_READ },
{ "ErrorsTo", "Errors to", mod_addrDN, ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DN | ATTR_FLAG_GROUP_MOD },
{ "rfc822RequestsTo", "Requests to", change_field, ATTR_FLAG_GROUP | ATTR_FLAG_READ },
{ "RequestsTo", "Requests to", mod_addrDN, ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DN | ATTR_FLAG_GROUP_MOD },
{ "moderator", "Moderated by", change_field, ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_GROUP_MOD },
{ "labeledURL", "More Info (URL)", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_GROUP | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_GROUP_MOD | ATTR_FLAG_IS_A_URL },
{ "onVacation", "On Vacation", set_boolean, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_IS_A_BOOL },
{ "vacationMessage", "Vacation Message", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD | ATTR_FLAG_IS_MULTILINE },
{ "drink", "Favorite Beverage", change_field, ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_PERSON_MOD },
{ "lastModifiedBy", "Last modified by", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_IS_A_DN | ATTR_FLAG_READ },
{ "lastModifiedTime", "Last modified at", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DATE },
{ "modifiersname", "Modifier's Name", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_IS_A_DN | ATTR_FLAG_READ },
{ "modifytimestamp", "Modify Timestamp", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DATE },
{ "creatorsname", "Creator's Name", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_IS_A_DN | ATTR_FLAG_READ },
{ "createtimestamp", "Create Timestamp", 0, ATTR_FLAG_GROUP | ATTR_FLAG_PERSON | ATTR_FLAG_READ | ATTR_FLAG_IS_A_DATE },
{ NULL, NULL, 0, ATTR_FLAG_NONE }
};

File diff suppressed because it is too large Load Diff

View File

@ -1,200 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 1992, 1993 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/ctype.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ldap.h>
#include "ud.h"
void
print_help( char *s )
{
int len; /* command length */
#ifdef DEBUG
if (debug & D_TRACE)
printf("->print_help(%s)\n", s);
#endif
if (s == NULL)
len = 0;
else {
len = strlen(s);
if (!strcasecmp(s, "commands"))
len = 0;
}
/* print general help, or just on topic 's' if provided */
if (len == 0) {
printf("\n Here are brief descriptions of available commands:\n\n");
printf(" ? To print this list.\n");
printf(" bind [who] To bind (authenticate) to the directory.\n");
printf(" cb [where] To change the search base.\n");
printf(" change [entry] To change information associated with an entry.\n");
printf(" create [group] To create a new group entry.\n");
printf(" dereference To toggle dereferencing of aliases.\n");
#ifdef UOFM
if (isatty( 1 )) {
#endif
printf(" vedit [entry] To edit a complete Directory entry using your editor.\n");
#ifdef UOFM
}
#endif
printf(" find [entry] To find an entry in the directory.\n");
printf(" groupbase [where] To change the group base.\n");
printf(" help [command] To display detailed help for a particular command.\n");
printf(" join [group] To subscribe to a group.\n");
printf(" list [who] To list the groups owned by someone.\n");
printf(" memberships [who] To list out the groups in which someone is a member.\n");
printf(" purge [group] To remove obsolete entries from a group.\n");
printf(" quit To terminate the program.\n");
printf(" remove [group] To remove a group entry.\n");
printf(" resign [group] To unsubscribe from a group.\n");
printf(" status To display directory connection status.\n");
printf(" tidy To unsubscribe from groups that no longer exist.\n");
printf(" verbose To toggle the verbose switch.\n");
printf("\n Type \"help <command-name>\" to get help about a particular command.");
printf("\n Type \"help options\" to get help about options in brackets above.\n");
#ifdef UOFM
printf("\n Bugs in ud should be reported via e-mail to: OpenLDAP-its@OpenLDAP.org\n" );
printf("\n For more assistance with ud, contact the ITD Consultants by phoning\n" );
printf(" 764-HELP or by sending e-mail to: consulting.help@umich.edu\n" );
#endif /* UOFM */
}
else if (!strncasecmp("options", s, len)) {
printf("\n");
format("Most commands need additional information in order to work. For example, the 'remove' command needs to know the name of the group to remove. This can be specified along with the 'remove' command, or the program will prompt you for the information.", 75, 2);
printf("\n");
printf(" [entry] An entry needs to be specified. This may be a person or a\n");
format("group. The name can be specified as either a ordinary name (e.g., 'Jane Doe'), or as some other identifying characteristic (e.g., 'uid=babs').", 75, 15);
printf("\n");
printf(" [group] A group in the Directory needs to be specified. This name\n");
format("should be specified as a ordinary name (e.g., 'Friends of maX500').", 75, 15);
printf("\n");
printf(" [where] A place in the Directory needs to be specified. This name\n");
format("should be specified as an LDAP-style name (e.g., 'ou=people, o=University of Michigan, c=United States of America'). In most cases, it is easier to omit the [where] and allow the program to guide you.", 75, 15);
printf("\n");
printf(" [who] A person in the Directory needs to be specified. This name\n");
format("can be specified as either a ordinary name (e.g., 'Jane Doe'), or as some other identifying characteristic (e.g., 'uid=babs').", 75, 15);
}
else if (!strncasecmp("list", s, len)) {
printf(" list [who]\n\n");
format("Prints out the list of groups owned by the person specified.", 75, 2);
}
else if (!strncasecmp("memberships", s, len)) {
printf(" memberships [who]\n\n");
format("Prints out the list of groups in which the person specified is a member.", 75, 2);
}
else if (!strncasecmp("vedit", s, len)) {
printf(" vedit [entry]\n\n");
format("Looks up the specified person in the Directory, and then writes this entry into a file. It then uses the EDITOR environment variable to select an editor, and then loads this file into the editor. The entry can now be modified in any way desired, and when the editor is exited, the entry will be written back into the Directory.", 75, 2);
}
else if (!strncasecmp("status", s, len)) {
printf(" status\n\n");
format("Prints out the current connection status. Lists the name of the current LDAP server, the current search base, the current group base, and the identity to which you are bound. If you have not bound as anyone then ud considers you bound as Nobody. cd is an alias for cb.", 75, 2);
}
else if (!strncasecmp("groupbase", s, len)) {
printf(" groupbase [where]\n\n");
format("The syntax and use of this command is identical to the more commonly used 'cb' command. This command sets the base which is used to create groups in the LDAP Directory. Setting the base to a certain value does not necessarily grant the person write-access to that part of the Directory in order to successfully create a group.", 75, 2);
}
else if (!strncasecmp("cd", s, len) || !strncasecmp("cb", s,len)) {
printf(" cb [where]\n");
printf(" cd [where]\n\n");
format("The cb command changes the search base. By default, this program looks only in the local part of the Directory. By using the cb command, you can search other parts of the Directory.", 75, 2);
printf("\n Examples:\n");
printf("\n * cb ..\n\n");
format("changes the search base so that it is one level higher in the Directory. Note that if you perform several of these in a row you will move to the root of the Directory tree.", 75, 2);
printf("\n * cb ?\n\n");
format("prints out a list of the possible areas to search below the current search base. This is useful once you have moved high in the tree and wish to snoop about.", 75, 2);
printf("\n * cb default\n\n");
format("sets the search base to its original default value.", 75, 2);
printf("\n * cb o=Merit Computer Network, c=US\n\n");
format("sets the search base to organization given, the Merit Computer Network in this case. This comamnd checks the validity of the specified search base, and rejects it if it is not a valid Distinguished Name (DN). A DN uniquely identifies a portion of the global LDAP namespace.", 75, 2);
}
else if (!strncasecmp("quit", s, len) || !strncasecmp("stop",s, len)) {
printf(" quit\n");
printf(" stop\n\n");
printf(" Quits the program. 'stop' is an alias for 'quit'.\n");
}
else if (!strncasecmp("find", s, len) || !strncasecmp("display", s, len) || !strncasecmp("show", s, len)) {
printf(" find [entry]\n");
printf(" show [entry]\n");
printf(" display [entry]\n\n");
format("Displays information about the person specified. If the name specified matches more than one person, one will be presented a list from which to make a choice. 'show' and 'display' are aliases for 'find.'", 75, 2);
}
else if (!strncasecmp("bind", s, len)) {
printf(" bind [who]\n\n");
format("Binds (authenticates) to the Directory. It is generally necessary to bind to the Directory in order to look at privileged entries or to modify an entry. Allows one to authenticate prior to issuing a 'change' or 'modify' command. Most often used by administrators to bind to an identity.", 75, 2);
}
else if (!strncasecmp("modify", s, len) || !strncasecmp("change", s, len)) {
printf(" modify [entry]\n");
printf(" change [entry]\n\n");
format("Changes information associated with an entry in the LDAP Directory. 'change' is an alias for 'modify'.", 75, 2);
}
else if (!strncasecmp("verbose", s, len)) {
printf(" verbose\n\n");
format("Turns on long and windy messages which might be useful to new users of this program. If verbose mode is already on, this turns it off.", 75, 2);
}
else if (!strncasecmp("dereference", s, len)) {
printf(" dereference\n\n");
format("Turns off following of aliases when searching, etc. If alias dereferencing has already been turned off, this turns it back on.", 75, 2);
}
else if (!strncasecmp("create", s, len)) {
printf(" create [group]\n\n");
format("Creates a new group in the Directory.", 75, 2);
}
else if (!strncasecmp("join", s, len) || !strncasecmp("subscribe", s, len)) {
printf(" join [group]\n");
printf(" subscribe [group]\n\n");
format("Adds the person as a subscriber to the specified group.", 75, 2);
}
else if (!strncasecmp("purge", s, len)) {
printf(" purge [group]\n\n");
format("Goes through the specified group looking for Distinguished Names that cannot be found. As it finds each one, it gives the person an opportunity to delete it.", 75, 2);
}
else if (!strncasecmp("resign", s, len) || !strncasecmp("unsubscribe", s, len)) {
printf(" resign [group]\n");
printf(" unsubscribe [group]\n\n");
format("Deletes the person from the specified group.", 75, 2);
}
else if (!strncasecmp("remove", s, len)) {
printf(" remove [group]\n\n");
format("Removes a group from the Directory.", 75, 2);
}
else if (!strncasecmp("help", s, len)) {
format("Prints out a brief description of each command.", 75, 2);
}
else if (!strncasecmp("tidy", s, len)) {
printf(" tidy\n\n");
format("Unsubscribes you from non-existent groups. Useful when you cannot resign from a group because, while your LDAP entry still contains a pointer to it, someone has removed a group of which you were a subscriber.", 75, 2);
}
else if (*s == '?') {
format("Prints out a brief description of each command. Same as typing 'help help'.", 75, 2);
}
else {
printf(" Don't recognize <%s>\n", s);
}
}

View File

@ -1,745 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 1991, 1992, 1993
* 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.
*
* The University of Michigan would like to thank the following people for
* their contributions to this piece of software:
*
* Robert Urquhart <robert@sfu.ca>
* Simon Fraser University, Academic Computing Services
*/
#include "portable.h"
#include <stdio.h>
#include <ac/stdlib.h>
#include <setjmp.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#include <ac/signal.h>
#include <ac/string.h>
#include <ac/ctype.h>
#include <ac/termios.h>
#include <ac/time.h>
#include <ac/unistd.h>
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include <ldap.h>
#include "ldap_defaults.h"
#include "ud.h"
/*
* Used with change_base() to indicate which base we are changing.
*/
#define BASE_SEARCH 0
#define BASE_GROUPS 1
#define iscom(x) (!strncasecmp((x), cmd, strlen(cmd)))
static char *server = NULL;
static char *config_file = UD_CONFIG_FILE;
static char *filter_file = FILTERFILE;
static int ldap_port = 0;
static int dereference = TRUE;
char *default_bind_object = NULL;
char *bound_dn; /* bound user's Distinguished Name */
char *group_base; /* place in LDAP tree where groups are */
char *search_base; /* place in LDAP tree where searches start */
static jmp_buf env; /* spot to jump to on an interrupt */
int lpp; /* lines per page */
int verbose; /* 1 if verbose mode on */
int col_size; /* characters across on the screen */
int bind_status; /* user's bind status */
LDAP *ld; /* LDAP descriptor */
LDAPFiltDesc *lfdp; /* LDAP filter descriptor */
#ifdef DEBUG
int debug; /* debug flag */
#endif
int ldebug; /* library debug flag */
#ifndef HAVE_MKVERSION
char Version[] = OPENLDAP_PACKAGE " " OPENLDAP_VERSION " UserDirectory (ud)";
#endif
int
main( int argc, char **argv )
{
register int c; /* for parsing argv */
register char *cp; /* for parsing Version */
verbose = 1;
/* handle argument list */
while ((c = getopt(argc, argv, "c:d:Df:l:p:s:u:vV")) != -1) {
switch (c) {
case 'l' :
ldebug |= (int) strtol(optarg, (char **) NULL, 0);
break;
case 'd' :
#ifdef DEBUG
debug |= (int) strtol(optarg, (char **) NULL, 0);
#endif
break;
case 's' :
server = strdup(optarg);
break;
case 'c' :
filter_file = strdup(optarg);
break;
case 'f' :
config_file = optarg;
break;
case 'p' :
ldap_port = atoi(optarg);
break;
case 'u' :
default_bind_object = strdup(optarg);
break;
case 'v' :
verbose = 1; /* this is the default anyways... */
break;
case 'V' :
verbose = 0;
break;
case 'D' :
printf("\n\n Debug flag values\n\n");
printf(" 1 function trace\n");
printf(" 2 find() information\n");
printf(" 4 group information\n");
printf(" 8 mod() information\n");
printf(" 16 parsing information\n");
printf(" 32 output information\n");
printf(" 64 authentication information\n");
printf(" 128 initialization information\n\n");
format("These are masks, and may be added to form multiple debug levels. For example, '-d 35' would perform a function trace, print out information about the find() function, and would print out information about the output routines too.", 75, 2);
exit( EXIT_SUCCESS );
default:
fprintf(stderr, "Usage: %s [-c filter-config-file] [-d debug-level] [-l ldap-debug-level] [-s server] [-p port] [-V]\n", argv[0]);
exit( EXIT_FAILURE);
/* NOTREACHED */
}
}
/* just print the first line of Version[] */
cp = strchr(Version, '\t');
if (cp != NULL)
*cp = '\0';
printf(Version);
fflush( stdout );
#ifdef SIGPIPE
(void) SIGNAL (SIGPIPE, SIG_IGN);
#endif
initialize_client();
initialize_attribute_strings();
/* now tackle the user's commands */
do_commands();
/* NOTREACHED */
return 0;
}
void
do_commands( void )
{
LDAPMessage *mp; /* returned by find() */
register char *cp; /* misc char pointer */
register char *ap; /* misc char pointer */
static char cmd[MED_BUF_SIZE]; /* holds the command */
static char input[MED_BUF_SIZE]; /* buffer for input */
#ifdef DEBUG
if (debug & D_TRACE)
printf("->do_commands()\n");
#endif
if (verbose)
printf("\n Enter a command. If you need help, type 'h' or '?' and hit RETURN.\n\n");
/* jump here on an interrupt */
(void) setjmp(env);
for (;;) {
printf("* ");
fflush(stdout);
cp = input;
/* Temporary kludge - if cp is null, dumps core under Solaris */
if (cp == NULL)
break;
fetch_buffer(input, sizeof(input), stdin);
if (*input == '\0') {
putchar('\n');
continue;
}
while (isspace((unsigned char)*cp))
cp++;
ap = cmd;
if (memset(cmd, '\0', sizeof(cmd)) == NULL)
fatal("memset");
while (!isspace((unsigned char)*cp) && (*cp != '\0'))
*ap++ = *cp++;
if (iscom("status"))
status();
else if (iscom("stop") || iscom("quit"))
break;
else if (iscom("cb") || iscom("cd") || iscom("moveto")) {
while (isspace((unsigned char)*cp) && (*cp != '\0'))
cp++;
if (!strncasecmp(cp, "base", 4))
cp += 4;
change_base(BASE_SEARCH, &search_base, nextstr(cp));
}
else if (iscom("memberships"))
(void) list_memberships(nextstr(cp));
else if (iscom("list"))
(void) list_groups(nextstr(cp));
else if (iscom("groupbase"))
change_base(BASE_GROUPS, &group_base, nextstr(cp));
else if (iscom("find") || iscom("display") || iscom("show")) {
cp = nextstr(cp);
if ((mp = find(cp, FALSE)) != NULL) {
parse_answer(mp);
print_an_entry();
ldap_msgfree(mp);
}
else
printf(" Could not find \"%s\".\n", cp);
}
#ifdef UOFM
else if (iscom("vedit") && isatty( 1 )) {
#else
else if (iscom("vedit")) {
#endif
(void) edit(nextstr(cp));
}
else if (iscom("modify") || iscom("change") || iscom("alter"))
(void) modify(nextstr(cp));
else if (iscom("bind") || iscom("iam"))
(void) auth(nextstr(cp), 0);
else if ((cmd[0] == '?') || iscom("help"))
print_help(nextstr(cp));
else if (iscom("join") || iscom("subscribe"))
(void) x_group(G_JOIN, nextstr(cp));
else if (iscom("resign") || iscom("unsubscribe"))
(void) x_group(G_RESIGN, nextstr(cp));
else if (!strncasecmp("create", cmd, strlen(cmd)))
add_group(nextstr(cp));
else if (!strncasecmp("remove", cmd, strlen(cmd)))
remove_group(nextstr(cp));
else if (!strncasecmp("purge", cmd, strlen(cmd)))
purge_group(nextstr(cp));
else if (!strncasecmp("verbose", cmd, strlen(cmd))) {
verbose = 1 - verbose;
if (verbose)
printf(" Verbose mode has been turned on.\n");
}
else if (!strncasecmp("dereference", cmd, strlen(cmd))) {
int deref;
dereference = 1 - dereference;
if (dereference == 1) {
deref = LDAP_DEREF_ALWAYS;
} else {
deref = LDAP_DEREF_NEVER;
}
ldap_set_option(ld, LDAP_OPT_DEREF, (void *) &deref);
}
else if (!strncasecmp("tidy", cmd, strlen(cmd)))
tidy_up();
else if (cmd[0] == '\0')
putchar('\n');
else
printf(" Invalid command. Type \"help commands.\"\n");
}
printf(" Thank you!\n");
ldap_unbind(ld);
exit( EXIT_SUCCESS );
/* NOTREACHED */
}
void
status( void )
{
register char **rdns;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->status()\n");
#endif
printf(" Current server is %s", server != NULL ? server : "<default>" );
if ( ld != NULL ) {
char *host = NULL;
ldap_get_option(ld, LDAP_OPT_HOST_NAME, &host);
if ( host != NULL &&
( server == NULL || strcasecmp( host, server ) != 0 ) )
{
printf( " (%s)", host );
}
}
putchar( '\n' );
printbase(" Search base is ", search_base);
printbase(" Group base is ", group_base);
if ( bound_dn != NULL ) {
rdns = ldap_explode_dn(bound_dn, TRUE);
printf(" Bound as \"%s\"\n", *rdns);
ldap_value_free(rdns);
} else {
printf(" Bound as Nobody\n" );
}
printf( " Verbose mode is %sabled\n", ( verbose ? "en" : "dis" ));
if ( ld != NULL ) {
int deref = LDAP_DEREF_NEVER;
ldap_get_option(ld, LDAP_OPT_DEREF, &deref);
printf( " Aliases are %sbeing dereferenced\n",
( deref == LDAP_DEREF_ALWAYS ) ? "" : "not" );
}
}
void
change_base( int type, char **base, char *s )
{
register char *cp; /* utility pointers */
char *output_string = NULL; /* for nice output */
int num_picked; /* # of selected base */
int j; /* used with num_picked */
int i = 1; /* index into choices array */
int matches; /* # of matches found */
int rest = 1; /* # left to display */
char tmp[MED_BUF_SIZE]; /* temporary buffer */
static char *choices[MED_BUF_SIZE]; /* bases from which to choose */
static char resp[SMALL_BUF_SIZE]; /* for prompting user */
static char buf[MED_BUF_SIZE];
static char *attrs[] = { "objectClass", NULL };
LDAPMessage *mp; /* results from a search */
LDAPMessage *ep; /* for going thru bases */
#ifdef DEBUG
if (debug & D_TRACE)
printf("->change_base(%s, %s)\n", s, s);
#endif
/*
* If s is NULL we need to prompt the user for an argument.
*/
if (s == NULL) {
if (verbose) {
printf(" You need to specify how the base is to be changed. Valid choices are:\n");
printf(" ? - list the choices immediately below this level\n");
printf(" .. - move up one level in the Directory tree\n");
printf(" root - move to the root of the Directory tree\n");
printf(" default - move to the default level built into this program\n");
printf(" <entry> - move to the entry specified\n");
}
printf(" Change base to? ");
fflush(stdout);
fetch_buffer(buf, sizeof(buf), stdin);
if ((buf != NULL) && (buf[0] != '\0'))
s = buf;
else
return;
}
/* set the output string */
if (type == BASE_SEARCH)
output_string = " Search base is now ";
else if (type == BASE_GROUPS)
output_string = " Group base is now ";
if (!strcasecmp(s, "root")) {
StrFreeDup(base, NULL);
printbase(" Search base is ", *base);
return;
}
/*
* User wants to ascend one level in the LDAP tree.
* Easy: Just strip off the first element of the
* current search base, unless it's the root, in
* which case we just do nothing.
*/
if (!strcasecmp(s, "..")) {
if (*base == NULL) {
printf(" You are already at the root\n");
return;
}
cp = strchr(*base, '=');
cp++;
/*
* If there isn't a second "=" in the base, then this was
* a one element base, and so now it should be NULL.
*/
if ((cp = strchr(cp, '=')) == NULL)
StrFreeDup(base, NULL);
else {
/*
* Back up to the start of this
*
* attr=value
*
* sequence now that 'cp' is pointing to the '='.
*/
while(!isspace((unsigned char)*cp))
cp--;
cp++;
/*
* Goofy, but need to do it this way since both *base
* and cp point into the same chunk of memory, and
* we want to free *base, but keep part of it around.
*/
cp = strdup(cp);
StrFreeDup(base, cp);
Free(cp);
}
printbase(output_string, *base);
return;
}
/* user wants to see what is directly below this level */
if (*s == '?') {
/*
* Fetch the list of entries directly below this level.
* Once we have the list, we will print it for the user, one
* screenful at a time. At the end of each screen, we ask
* the user if they want to see more. They can also just
* type a number at that point too.
*/
if (ldap_search_s(ld, *base, LDAP_SCOPE_ONELEVEL, NULL, attrs, FALSE, &mp) != LDAP_SUCCESS) {
int ld_errno = 0;
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
if ((ld_errno == LDAP_TIMELIMIT_EXCEEDED) ||
(ld_errno == LDAP_SIZELIMIT_EXCEEDED)) {
if (verbose) {
printf(" Your query was too general and a limit was exceeded. The results listed\n");
printf(" are not complete. You may want to try again with a more refined query.\n\n");
}
else
printf(" Time or size limit exceeded. Partial results follow.\n\n");
} else {
ldap_perror(ld, "ldap_search_s");
return;
}
}
if ((matches = ldap_count_entries(ld, mp)) < 1) {
printf(" There is nothing below this level.\n");
(void) ldap_msgfree(mp);
return;
}
num_picked = 0;
printf(" There are %d choices:\n", matches);
for (ep = ldap_first_entry(ld, mp); ep != NULL; ep = ldap_next_entry(ld, ep)) {
/*
* Put the last component of the DN into 'lastDN'.
* If we are at the root level, convert any country
* codes to recognizable names for printing.
*/
choices[i] = ldap_get_dn(ld, ep);
printf(" %2d. %s\n", i, choices[i]);
i++;
if ((rest++ > (lpp - 3)) && (i < matches)) {
printf("More? ");
fflush(stdout);
fetch_buffer(resp, sizeof(resp), stdin);
if ((resp[0] == 'n') || (resp[0] == 'N'))
break;
else if (((num_picked = atoi(resp)) != 0) && (num_picked < i))
break;
rest = 1;
}
}
for (;;) {
if (num_picked != 0) {
j = num_picked;
num_picked = 0;
}
else {
printf(" Which number? ");
fflush(stdout);
fetch_buffer(resp, sizeof(resp), stdin);
j = atoi(resp);
}
if (j == 0) {
(void) ldap_msgfree(mp);
for (i = 0; i < matches; i++)
ldap_memfree(choices[i]);
return;
}
if ((j < 1) || (j >= i))
printf(" Invalid number\n");
else {
StrFreeDup(base, choices[j]);
printbase(output_string, *base);
(void) ldap_msgfree(mp);
for (i = 0; choices[i] != NULL; i++)
ldap_memfree(choices[i]);
return;
}
}
}
/* set the search base back to the original default value */
else if (!strcasecmp(s, "default")) {
if (type == BASE_SEARCH)
StrFreeDup(base, NULL);
else if (type == BASE_GROUPS)
StrFreeDup(base, UD_WHERE_GROUPS_ARE_CREATED);
printbase(output_string, *base);
}
/* they typed in something -- see if it is legit */
else {
/* user cannot do something like 'cb 33' */
if (atoi(s) != 0) {
printf(" \"%s\" is not a valid search base\n", s);
printf(" Base unchanged.\n");
printf(" Try using 'cb ?'\n");
return;
}
/* was it a fully-specified DN? */
if (vrfy(s)) {
StrFreeDup(base, s);
printbase(output_string, *base);
return;
}
/* was it a RDN relative to the current base? */
sprintf(tmp, "ou=%s, %s", s, *base);
if (vrfy(tmp)) {
StrFreeDup(base, tmp);
printbase(output_string, *base);
return;
}
printf(" \"%s\" is not a valid base\n Base unchanged.\n", s);
}
}
void
initialize_client( void )
{
FILE *fp; /* for config file */
static char buffer[MED_BUF_SIZE]; /* for input */
#ifdef HAVE_GETPWUID
struct passwd *pw; /* for getting the home dir */
#endif
register char *cp; /* for fiddling with buffer */
char *config; /* config file to use */
static char bp[1024]; /* for tty set-up */
#ifdef DEBUG
if (debug & D_TRACE)
printf("->initialize_client()\n");
#endif
if (ldebug) {
ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldebug );
ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &ldebug );
}
/*
* A per-user config file has precedence over any system-wide
* config file, if one exists.
*/
#ifdef HAVE_GETPWUID
if ((pw = getpwuid((uid_t) geteuid())) == (struct passwd *) NULL)
config = config_file;
else {
if (pw->pw_dir == NULL)
config = config_file;
else {
sprintf(buffer, "%s/%s", pw->pw_dir,
UD_USER_CONFIG_FILE);
if (access(buffer, R_OK) == 0)
config = buffer;
else
config = config_file;
}
}
#else
config = config_file;
#endif /* getpwduid() */
#ifdef DEBUG
if (debug & D_INITIALIZE)
printf("Using config file %s\n", config);
#endif
/*
* If there is a config file, read it.
*
* Could have lines that look like this:
*
* server <ip-address or domain-name>
* base <default search base>
* groupbase <default place where groups are created>
*
*/
if ((fp = fopen(config, "r")) != NULL) {
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
buffer[strlen(buffer) - 1] = '\0';
if (!strncasecmp(buffer, "server", 6)) {
if (server != NULL)
continue;
cp = buffer + 6;
while (isspace((unsigned char)*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
server = strdup(cp);
}
else if (!strncasecmp(buffer, "host", 4)) {
if (server != NULL)
continue;
cp = buffer + 4;
while (isspace((unsigned char)*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
server = strdup(cp);
}
else if (!strncasecmp(buffer, "base", 4)) {
cp = buffer + 4;
while (isspace((unsigned char)*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
search_base = strdup(cp);
}
else if (!strncasecmp(buffer, "groupbase", 9)) {
cp = buffer + 9;
while (isspace((unsigned char)*cp))
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
group_base = strdup(cp);
}
else
fprintf(stderr, "?? -> %s\n", buffer);
}
}
if (group_base == NULL)
group_base = strdup(UD_WHERE_GROUPS_ARE_CREATED);
/*
* Set up our LDAP connection. The values of retry and timeout
* are meaningless since we will immediately be doing a null bind
* because we want to be sure to use TCP, not UDP.
*/
if ((ld = ldap_init(server, ldap_port)) == NULL) {
fprintf(stderr, " Initialization of LDAP session failed.\n");
exit( EXIT_FAILURE );
/* NOTREACHED */
}
if (ldap_bind_s(ld, (char *) default_bind_object, NULL,
LDAP_AUTH_SIMPLE) != LDAP_SUCCESS) {
ldap_perror(ld, " ldap_bind_s");
exit( EXIT_FAILURE );
/* NOTREACHED */
}
{
int deref = LDAP_DEREF_ALWAYS;
ldap_set_option(ld, LDAP_OPT_DEREF, (void *) &deref);
}
bind_status = UD_NOT_BOUND;
if ( default_bind_object != NULL ) {
bound_dn = strdup(default_bind_object);
} else {
bound_dn = NULL;
}
/* enabled local caching of ldap results, 15 minute lifetime */
ldap_enable_cache( ld, 60 * 15, 0 ); /* no memory limit */
/* initialize the search filters */
if ((lfdp = ldap_init_getfilter(filter_file)) == NULL) {
fprintf(stderr, " Problem with ldap_init_getfilter\n");
fatal(filter_file);
/*NOTREACHED*/
}
/* terminal initialization stuff goes here */
lpp = DEFAULT_TTY_HEIGHT;
col_size = DEFAULT_TTY_WIDTH;
(void) SIGNAL (SIGINT, attn);
#ifndef NO_TERMCAP
{
char *term;
if (((term = getenv("TERM")) == NULL) || (tgetent(bp, term) <= 0))
return;
else {
#ifdef TIOCGWINSZ
struct winsize win; /* for tty set-up */
if (ioctl(fileno(stdout), TIOCGWINSZ, &win) >= 0) {
if ((lpp = win.ws_row) == 0)
lpp = tgetnum("li");
if ((col_size = win.ws_col) == 0)
col_size = tgetnum("co");
if ((lpp <= 0) || tgetflag("hc"))
lpp = DEFAULT_TTY_HEIGHT;
if ((col_size <= 0) || tgetflag("hc"))
col_size = DEFAULT_TTY_WIDTH;
(void) SIGNAL (SIGWINCH, chwinsz);
} else
#endif
{
lpp = tgetnum("li");
col_size = tgetnum("co");
}
}
}
#endif
}
RETSIGTYPE
attn( int sig )
{
fflush(stderr);
fflush(stdout);
printf("\n\n INTERRUPTED!\n");
(void) SIGNAL_REINSTALL (SIGINT, attn);
longjmp(env, 1);
}
#if !defined(NO_TERMCAP) && defined(TIOCGWINSZ)
RETSIGTYPE
chwinsz( int sig )
{
struct winsize win;
(void) SIGNAL (SIGWINCH, SIG_IGN);
if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
if (win.ws_row != 0)
lpp = win.ws_row;
if (win.ws_col != 0)
col_size = win.ws_col;
}
(void) SIGNAL_REINSTALL (SIGWINCH, chwinsz);
}
#endif

View File

@ -1,807 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 1991,1993 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/stdlib.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ldap.h>
#include "ud.h"
static char *get_URL( void );
static int check_URL( char *url );
void
modify( char *who )
{
LDAPMessage *mp; /* returned from find() */
char *dn; /* distinguished name */
char **rdns; /* for fiddling with the DN */
char name[MED_BUF_SIZE]; /* entry to modify */
int displayed_choices = 0;
static char ans[SMALL_BUF_SIZE]; /* for holding user input */
#ifdef UOFM
static char printed_warning = 0; /* for use with the */
struct attribute no_batch_update_attr;
int ld_errno;
#endif
int is_a_group; /* TRUE if it is; FALSE otherwise */
#ifdef DEBUG
if (debug & D_TRACE)
printf("->modify(%s)\n", who);
#endif
/*
* Require them to bind first if the are modifying a group.
*/
if (bind_status == UD_NOT_BOUND) {
if (auth((char *) NULL, 1) < 0)
return;
}
/*
* First, decide what entry we are going to modify. If the
* user has not included a name on the modify command line,
* we will use the person who was last looked up with a find
* command. If there is no value there either, we don't know
* who to modify.
*
* Once we know who to modify, be sure that they exist, and
* parse out their DN.
*/
if (who == NULL) {
if (verbose) {
printf(" Enter the name of the person or\n");
printf(" group whose entry you want to modify: ");
}
else
printf(" Modify 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));
rdns = ldap_explode_dn(dn, TRUE);
if (verbose)
printf("\n Modifying Directory entry of \"%s\"\n", *rdns);
#ifdef UOFM
/*
* If verbose mode is turned on and the user has not set a value
* for noBatchUpdates, warn them that what they are about to do
* may be overwritten automatically by that Stinkbug.
*/
no_batch_update_attr.quipu_name = "noBatchUpdates";
(void) fetch_boolean_value(dn, no_batch_update_attr);
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
if (verbose && !printed_warning && (ld_errno == LDAP_NO_SUCH_ATTRIBUTE)) {
printed_warning = 1;
printf("\n WARNING!\n");
printf(" You are about to make a modification to an LDAP entry\n");
printf(" that has its \"automatic updates\" field set to ON.\n");
printf(" This means that the entry will be automatically updated\n");
printf(" each month from official University sources like the\n");
printf(" Personnel Office. With \"automatic updates\" set to ON,\n");
printf(" the following fields will be overwritten each month:\n");
printf(" Title, home address and phone,\n");
printf(" business address and phone\n");
printf(" If you modify any of these fields, you may want to change\n");
printf(" the \"automatic updates\" field to OFF so that your\n");
printf(" changes will not be overwritten. You may change this\n");
printf(" setting by choosing \"u\" at the \"Modify what?\" prompt\n");
}
#endif
/*
* Current values for user 'who' are being held in 'mp'. We
* should parse up that buffer and fill in the Entry structure.
* Once we're done with that, we can find out which fields the
* user would like to modify.
*/
parse_answer(mp);
is_a_group = isgroup();
(void) ldap_msgfree(mp);
printf(" You now need to specify what field you'd like to modify.\n");
for (;;) {
if ( verbose || !displayed_choices ) {
printf("\n Choices are:\n");
printf(" -----------------------\n");
print_mod_list(is_a_group);
printf("\n Pressing Return will cancel the process.\n");
displayed_choices = 1;
}
printf("\n Modify what? ");
fflush(stdout);
fetch_buffer(ans, sizeof(ans), stdin);
if (ans[0] == '\0')
break;
perform_action(ans, dn, is_a_group);
if ((mp = find(*rdns, TRUE)) == NULL)
break;
parse_answer(mp);
(void) ldap_msgfree(mp);
}
ldap_memfree(dn);
ldap_value_free(rdns);
return;
}
/* generic routine for changing any field */
void
change_field(
char *who, /* DN of entry we are changing */
int attr_idx /* attribute to change */
)
{
struct attribute attr = Entry.attrs[attr_to_index(attrlist[attr_idx].quipu_name)];
#define IS_MOD(x) (!strncasecmp(resp, (x), strlen(resp)))
static char buf[MED_BUF_SIZE]; /* for printing things */
static char resp[SMALL_BUF_SIZE]; /* for user input */
char *prompt, *prompt2, *more;
register int i; /* for looping thru values */
static LDAPMod mod;
static LDAPMod *mods[2] = { &mod }; /* passed to ldap_modify */
static char *values[MAX_VALUES]; /* passed to ldap_modify */
#ifdef DEBUG
if (debug & D_TRACE)
printf("->change_field(%x, %s)\n", attr, who);
#endif
/*
* If there is no current value associated with the attribute,
* then this is the easy case. Collect one (or more) attributes
* from the user, and then call ldap_modify_s() to write the changes
* to the LDAP server.
*/
for (i = 0; i < MAX_VALUES; i++)
values[i] = NULL;
if (attr.values == (char **) NULL) {
printf("\n No current \"%s\"\n", attr.output_string);
values[0] = get_value(attr.quipu_name, "Enter a value");
if ( values[0] == NULL )
return;
mod.mod_op = LDAP_MOD_REPLACE;
mod.mod_type = attr.quipu_name;
mod.mod_values = values;
for (i = 1; i < MAX_VALUES; i++) {
printf(" Do you wish to add an additional value? ");
fflush(stdout);
fetch_buffer(resp, sizeof(resp), stdin);
if ((resp[0] == 'y') || (resp[0] == 'Y'))
values[i] = get_value(attr.quipu_name, "Enter an additional value");
else
break;
}
#ifdef DEBUG
if (debug & D_MODIFY) {
printf(" ld = 0x%x\n", ld);
printf(" who = [%s]\n", who);
printf(" mods[0]->mod_op = %1d\n", mods[0]->mod_op);
printf(" mods[0]->mod_type = %s\n", mods[0]->mod_type);
for (i = 0; mods[0]->mod_values[i] != NULL; i++)
printf(" mods[0]->mod_values[%1d] = %s\n", i, mods[0]->mod_values[i]);
}
#endif
if (ldap_modify_s(ld, who, mods)) {
mod_perror(ld);
return;
}
else if (verbose)
printf(" Modification of '%s' complete.\n", attr.output_string);
ldap_uncache_entry( ld, who );
for (i--; i > 0; i--)
(void) Free(values[i]);
}
/*
* There are values for this attribute already. In this case,
* we want to allow the user to delete all existing values,
* add additional values to the ones there already, or just
* delete some of the values already present. DIXIE does not
* handle modifications where the attribute occurs on the LHS
* more than once. So to delete entries and add entries, we
* need to call ldap_modify() twice.
*/
else {
/*
* If the attribute holds values which are DNs, print them
* in a most pleasant way.
*/
sprintf(buf, "%s: ", attr.output_string);
if (!strcmp(attr.quipu_name, "owner"))
(void) print_DN(attr);
else
(void) print_values(attr);
if (verbose) {
printf(" You may now:\n");
printf(" Add additional values to the existing ones, OR\n");
printf(" Clear all values listed above, OR\n");
printf(" Delete one of the values listed above, OR\n");
printf(" Replace all of the values above with new ones.\n");
}
printf("\n Add, Clear, Delete, or Replace? ");
fflush(stdout);
fetch_buffer(resp, sizeof(resp), stdin);
/*
* Bail if they just hit the RETURN key.
*/
if (resp[0] == '\0') {
if (verbose)
printf("\n No changes made.\n");
return;
}
/*
* If the want to clear the values, just do it.
*/
mod.mod_type = attr.quipu_name;
mod.mod_values = values;
if (IS_MOD("clear")) {
mod.mod_op = LDAP_MOD_DELETE;
mod.mod_values = NULL;
if ( verbose && !confirm_action( "All existing values will be removed." )) {
printf(" Modification halted.\n");
return;
}
#ifdef DEBUG
if (debug & D_MODIFY) {
printf("Clearing attribute '%s'\n", attr.quipu_name);
printf("who = [%s]\n", who);
printf("mod = [%d] [%s] [%x]\n", mod.mod_op,
mod.mod_type, mod.mod_values);
}
#endif
if (ldap_modify_s(ld, who, mods)) {
mod_perror(ld);
return;
}
else if (verbose)
printf(" '%s' has been cleared.\n", attr.output_string);
ldap_uncache_entry( ld, who );
return;
}
if (IS_MOD("add")) {
prompt = "Enter the value you wish to add";
more = " Add an additional value? ";
prompt2 = "Enter another value you wish to add";
mod.mod_op = LDAP_MOD_ADD;
}
else if (IS_MOD("delete")) {
prompt = "Enter the value you wish to delete";
more = " Delete an additional value? ";
prompt2 = "Enter another value you wish to delete";
mod.mod_op = LDAP_MOD_DELETE;
}
else if (IS_MOD("replace")) {
prompt = "Enter the new value";
more = " Add an additional value? ";
prompt2 = "Enter another value you wish to add";
mod.mod_op = LDAP_MOD_REPLACE;
if ( verbose && !confirm_action( "All existing values will be overwritten with the new values you are about to enter." )) {
printf(" Modification halted.\n");
return;
}
}
else {
printf(" No changes made.\n");
return;
}
values[0] = get_value(attr.quipu_name, prompt);
for (i = 1; i < MAX_VALUES; i++) {
printf(more);
fflush(stdout);
fetch_buffer(resp, sizeof(resp), stdin);
if ((resp[0] == 'y') || (resp[0] == 'Y'))
values[i] = get_value(attr.quipu_name, prompt2);
else
break;
}
/* if the first value in the value-array is NULL, bail */
if (values[0] == NULL) {
if (verbose)
printf(" No modification made.\n");
return;
}
#ifdef DEBUG
if (debug & D_MODIFY) {
printf(" ld = 0x%x\n", ld);
printf(" who = [%s]\n", who);
printf(" mods[0]->mod_op = %1d\n", mods[0]->mod_op);
printf(" mods[0]->mod_type = %s\n", mods[0]->mod_type);
for (i = 0; mods[0]->mod_values[i] != NULL; i++)
printf(" mods[0]->mod_values[%1d] = %s\n", i, mods[0]->mod_values[i]);
}
#endif
if (ldap_modify_s(ld, who, mods)) {
mod_perror(ld);
return;
}
else if (verbose)
printf(" Modifications to '%s' complete.\n", attr.output_string);
ldap_uncache_entry( ld, who );
for (i--; i > 0; i--)
(void) Free(values[i]);
}
return;
}
/*
* These are used to size the buffers we use when collecting values that
* can cross more than one line.
*/
#define LINE_SIZE 80
#define MAX_LINES 6
#define MAX_DESC_LINES 24
#define INTL_ADDR_LIMIT 30
char *
get_value( char *id, char *prompt )
{
char *cp; /* for the Malloc() */
int count; /* line # of new value -- if multiline */
int multiline = 0; /* 1 if this value is multiline */
static char line[LINE_SIZE]; /* raw line from user */
static char buffer[MAX_DESC_LINES * (LINE_SIZE+2)]; /* holds ALL of the
lines we get */
#ifdef DEBUG
if (debug & D_TRACE)
printf("->get_value(%s, %s)\n", id, prompt);
#endif
/* if this is a URL, have another routine handle this */
if (!strcmp(id, "labeledURL"))
return(get_URL());
/*
* To start with, we have one line of input from the user.
*
* Addresses and multiline description can span multiple lines.
* Other attributes may not.
*/
count = 1;
(void) memset(buffer, '\0', sizeof(buffer));
#ifdef UOFM
if (!strcmp(id, "postalAddress") || !strcmp(id, "homePostalAddress") || !strcmp(id, "multiLineDescription") || !strcmp(id, "vacationMessage"))
#else
if (!strcmp(id, "postalAddress") || !strcmp(id, "homePostalAddress"))
#endif
multiline = 1;
printf("\n %s:\n", prompt);
/* fetch lines */
for (;;) {
if (multiline)
printf(" %1d: ", count);
else
printf(" > ");
fflush(stdout);
fetch_buffer(line, sizeof(line), stdin);
if (line[0] == '\0')
break;
#ifdef UOFM
/*
* Screen out dangerous e-mail addresses of the form:
*
* user@umich.edu
*
* and addresses that have no '@' symbol at all.
*/
if (!strcmp(id, "mail")) {
int i;
char *tmp, *tmp2;
/* if this is a group, don't worry */
if (isgroup())
goto mail_is_good;
/* if this address is not @umich.edu, don't worry */
/* ...unless there is no '@' at all! */
tmp = strdup(line);
if ((tmp2 = strrchr(tmp, '@')) == NULL) {
printf("\n");
format("The address you entered is not a valid e-mail address. E-mail addresses should be of the form \"local@domain\", e.g. bjensen@b.imap.itd.umich.edu", 75, 2 );
goto mail_is_bad;
}
*tmp2 = '\0';
tmp2++;
if (strcasecmp(tmp2, "umich.edu"))
goto mail_is_good;
/* if not of the form uid@umich.edu, don't worry */
if ((i = attr_to_index("uid")) < 0)
goto mail_is_good;
if (strcasecmp(tmp, *(Entry.attrs[i].values)))
goto mail_is_good;
printf("\n");
format("An e-mail address of the form uniqname@umich.edu is not the form that you want registered in the Directory. This form is the one to use on business cards, for example, but the Directory should contain your real e-mail address; that is, the address where you really read your mail.", 75, 2);
mail_is_bad:
printf("\n");
printf(" Please enter a legal e-mail address (or press RETURN to stop)\n");
continue;
}
mail_is_good:
#endif
/*
* If the attribute which we are gathering is a "owner"
* then we should lookup the name. The user is going to
* either have to change the search base before doing the
* modify or the person is going to have to be within the
* scope of the current search base.
*/
if (!strcmp(id, "owner")) {
LDAPMessage *lmp, *elmp;
char *tmp;
lmp = find(line, FALSE);
if (lmp == (LDAPMessage *) NULL) {
printf(" Could not find \"%s\" in the Directory\n", line);
if (verbose)
format("Owners of groups must be valid entries in the LDAP Directory. The name you have typed above could not be found in the LDAP Directory.", 72, 2);
return(NULL);
}
elmp = ldap_first_entry(ld, lmp);
if (lmp == (LDAPMessage *) NULL) {
ldap_perror(ld, "ldap_first_entry");
return(NULL);
}
tmp = ldap_get_dn(ld, elmp);
strcpy(buffer, tmp);
ldap_memfree(tmp);
(void) ldap_msgfree(lmp);
break;
}
if (!strcmp(id, "postalAddress") || !strcmp(id, "homePostalAddress")) {
if (strlen(line) > INTL_ADDR_LIMIT) {
printf(" The international standard for addresses only allows for 30-character lines\n");
printf(" Please re-enter your last line.\n");
continue;
}
}
/*
* Separate lines of multiline attribute values with
* dollar signs. Copy this line into the buffer we
* use to collect up all of the user-supplied input
* lines. If this is not a multiline attribute, we
* are done.
*/
if (count++ > 1)
(void) strcat(buffer, " $ ");
(void) strcat(buffer, line);
if (!multiline)
break;
if ((count > MAX_LINES) && (!strcmp(id, "postalAddress") || !strcmp(id, "homePostalAddress"))) {
printf(" The international standard for addresses only allows for six lines\n");
break;
}
#ifdef UOFM
if ((count > MAX_DESC_LINES) && !strcmp(id, "multiLineDescription")) {
printf(" We only allow %d lines of description\n", MAX_DESC_LINES);
break;
}
#endif
}
if (buffer[0] == '\0')
return(NULL);
#ifdef DEBUG
if (debug & D_MODIFY)
printf(" Value is [%s]\n", buffer);
#endif
cp = (char *) Malloc((unsigned) (strlen(buffer) + 1));
strcpy(cp, buffer);
return(cp);
}
void
set_boolean(
char *who, /* DN of entry we are changing */
int attr_idx /* boolean attribute to change */
)
{
struct attribute attr = Entry.attrs[attr_to_index(attrlist[attr_idx].quipu_name)];
char *cp, *s;
static char response[16];
static char *newsetting[2] = { NULL, NULL };
LDAPMod mod, *mods[2];
#ifdef DEBUG
if (debug & D_TRACE)
printf("->set_boolean(%s, %s)\n", who, attr.quipu_name);
#endif
mods[0] = &mod;
mods[1] = (LDAPMod *) NULL;
mod.mod_op = LDAP_MOD_REPLACE;
mod.mod_type = attr.quipu_name;
mod.mod_values = newsetting;
/* fetch the current setting */
if ((cp = fetch_boolean_value(who, attr)) == NULL)
return;
if (!strcmp(cp, "TRUE"))
newsetting[0] = "FALSE";
else if (!strcmp(cp, "FALSE"))
newsetting[0] = "TRUE";
else {
printf(" This field needs to be set to either TRUE or to FALSE.\n");
printf(" \"%s\" is not a legal value. Please set this field to either TRUE or to FALSE.\n", cp);
newsetting[0] = "FALSE";
}
/* see if they want to change it */
printf("\n");
printf(" The current value of this field is %s.\n", cp);
printf(" Should I change the value of this field to %s?\n",
newsetting[0]);
printf(" Please enter Y for yes, N for no, or RETURN to cancel: ");
fflush(stdout);
(void) fetch_buffer(response, sizeof(response), stdin);
for (s = response; isspace((unsigned char)*s); s++)
;
if ((*s == 'y') || (*s == 'Y')) {
if (ldap_modify_s(ld, who, mods)) {
mod_perror(ld);
return;
}
else if (verbose)
printf(" Setting has been changed\n");
ldap_uncache_entry(ld, who);
return;
}
if (verbose)
printf(" Setting has not been changed\n");
}
#ifdef UOFM
void
set_updates( char *who, int dummy )
{
char *cp, *s;
static char response[16];
static char value[6];
static char *newsetting[2] = { value, NULL };
LDAPMod mod, *mods[2];
struct attribute attr;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->set_updates(%s)\n", who);
#endif
mods[0] = &mod;
mods[1] = (LDAPMod *) NULL;
mod.mod_op = LDAP_MOD_REPLACE;
mod.mod_type = "noBatchUpdates";
mod.mod_values = newsetting;
/* explain what the implications are */
if (verbose) {
printf("\n By default, updates that are received from the Personnel\n");
printf(" Office and the Office of the Registrar are applied to all\n");
printf(" entries in the LDAP database each month. Sometimes this\n");
printf(" feature is undesirable. For example, if you maintain your\n");
printf(" entry in the LDAP database manually, you may not want to\n");
printf(" have these updates applied to your entry, possibly overwriting\n");
printf(" correct information with out-dated information.\n\n");
}
/* fetch the current setting */
attr.quipu_name = "noBatchUpdates";
if ((cp = fetch_boolean_value(who, attr)) == NULL)
return;
if (!strcmp(cp, "TRUE"))
printf(" Automatic updates are currently turned OFF\n");
else if (!strcmp(cp, "FALSE"))
printf(" Automatic updates are currently turned ON\n");
else {
fprintf(stderr, " Unknown update flag -> [%s]\n", cp);
return;
}
/* see if they want to change it */
printf("\n Change this setting [no]? ");
fflush(stdout);
(void) fetch_buffer(response, sizeof(response), stdin);
for (s = response; isspace((unsigned char)*s); s++)
;
if ((*s == 'y') || (*s == 'Y')) {
if (!strcmp(cp, "TRUE"))
strcpy(value, "FALSE");
else
strcpy(value, "TRUE");
if (ldap_modify_s(ld, who, mods)) {
mod_perror(ld);
return;
}
else if (verbose)
printf(" Setting has been changed\n");
ldap_uncache_entry( ld, who );
return;
}
if (verbose)
printf(" Setting has not been changed\n");
}
#endif
void
print_mod_list( int group )
{
register int i, j = 1;
if (group == TRUE) {
for (i = 0; attrlist[i].quipu_name != NULL; i++) {
if (attrlist[i].flags & ATTR_FLAG_GROUP_MOD) {
printf(" %2d -> %s\n", j, attrlist[i].output_string);
j++;
}
}
} else {
for (i = 0; attrlist[i].quipu_name != NULL; i++) {
if (attrlist[i].flags & ATTR_FLAG_PERSON_MOD) {
printf(" %2d -> %s\n", j, attrlist[i].output_string);
j++;
}
}
}
printf(" ? -> Print this list\n\n");
printf(" Press the RETURN key without typing a number to quit.\n");
#ifdef UOFM
if (group == FALSE)
printf(" To add nicknames, send mail to x500-nicknames@umich.edu\n");
#endif
}
int
perform_action( char *choice, char *dn, int group )
{
int selection;
register int i, j = 1;
selection = atoi(choice);
if (selection < 1) {
printf("\n Choices are:\n");
printf(" -----------------------\n");
print_mod_list(group);
return(1);
/* NOTREACHED */
}
if (group == TRUE) {
for (i = 0; attrlist[i].quipu_name != NULL; i++) {
if (attrlist[i].flags & ATTR_FLAG_GROUP_MOD) {
if (j == selection)
break;
j++;
}
}
} else {
for (i = 0; attrlist[i].quipu_name != NULL; i++) {
if (attrlist[i].flags & ATTR_FLAG_PERSON_MOD) {
if (j == selection)
break;
j++;
}
}
}
if (attrlist[i].quipu_name == NULL) {
printf("\n Choices are:\n");
printf(" -----------------------\n");
print_mod_list(group);
return(1);
/* NOTREACHED */
}
(*attrlist[i].mod_func)(dn, i);
return(0);
}
static char *
get_URL( void )
{
char *rvalue, label[MED_BUF_SIZE], url[MED_BUF_SIZE];
if (verbose) {
printf(" First, enter the URL. (Example: http://www.us.itd.umich.edu/users/).\n");
printf(" The URL may be up to %d characters long.\n", MED_BUF_SIZE);
}
for (;;) {
printf(" URL: ");
fflush(stdout);
(void) fetch_buffer(url, sizeof(url), stdin);
if (*url == '\0')
continue;
if (check_URL(url) == 0)
break;
printf(" A URL may not have any spaces or tabs in it. Please re-enter your URL.\n\n");
}
if (verbose)
printf("\n Now please enter a descriptive label for this URL\n");
do {
printf(" Label: ");
fflush(stdout);
(void) fetch_buffer(label, sizeof(label), stdin);
} while (label[0] == '\0');
rvalue = (char *) Malloc((unsigned) (strlen(url) + 2 + strlen(label)));
sprintf(rvalue, "%s %s", url, label);
return((char *) rvalue);
}
static int
check_URL( char *url )
{
register char *cp;
for (cp = url; *cp != '\n' && *cp != '\0'; cp++) {
if (isspace((unsigned char)*cp))
return(-1);
/*NOTREACHED*/
}
*cp = '\0';
return(0);
}
void
mod_perror( LDAP *ld )
{
int ld_errno = LDAP_SUCCESS;
char *ld_errtext = NULL;
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno );
if( ld_errno != LDAP_SUCCESS ) {
ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &ld_errtext );
}
fprintf( stderr, " modify failed: %s (%d)\n",
ldap_err2string( ld_errno ), ld_errno );
if( ld_errtext != NULL ) {
fprintf( stderr, " additional information: %s\n",
ld_errtext );
}
fprintf( stderr, " Please try again later.\n" );
}

View File

@ -1,681 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 1991, 1993
* 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/ctype.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ldap.h>
#include "ud.h"
struct entry Entry;
static char *time2text(char *ldtimestr, int dateonly);
static long gtime(struct tm *tm);
/*
* When displaying entries, display only these attributes, and in this
* order.
*/
static char *person_attr_print_order[] = {
"cn",
"mail",
"telephoneNumber",
"facsimileTelephoneNumber",
"pager",
"postalAddress",
"title",
"uid",
"multiLineDescription",
"homePhone",
"homePostalAddress",
"drink",
"labeledURL",
"onVacation",
"vacationMessage",
"memberOfGroup",
"lastModifiedBy",
"lastModifiedTime",
"modifiersname",
"modifytimestamp",
NULL
};
static char *group_attr_print_order[] = {
"cn",
"facsimileTelephoneNumber",
"telephoneNumber",
"postalAddress",
"multiLineDescription",
"joinable",
"associatedDomain",
"owner",
"moderator",
"ErrorsTo",
"rfc822ErrorsTo",
"RequestsTo",
"rfc822RequestsTo",
"member",
"mail",
"labeledURL",
"lastModifiedBy",
"lastModifiedTime",
"modifiersname",
"modifytimestamp",
"creatorsname",
"createtimestamp",
NULL
};
void
parse_answer( LDAPMessage *s )
{
int idx;
char **rdns;
register LDAPMessage *ep;
register char *ap;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->parse_answer(%x)\n", s);
#endif
clear_entry();
#ifdef DEBUG
if (debug & D_PARSE)
printf(" Done clearing entry\n");
#endif
for (ep = ldap_first_entry(ld, s); ep != NULL; ep = ldap_next_entry(ld, ep)) {
BerElement *cookie = NULL;
#ifdef DEBUG
if (debug & D_PARSE)
printf(" Determining DN and name\n");
#endif
Entry.DN = ldap_get_dn(ld, ep);
#ifdef DEBUG
if (debug & D_PARSE)
printf(" DN = %s\n", Entry.DN);
#endif
rdns = ldap_explode_dn(Entry.DN, TRUE);
#ifdef DEBUG
if (debug & D_PARSE)
printf(" Name = %s\n", *rdns);
#endif
Entry.name = strdup(*rdns);
ldap_value_free(rdns);
for (ap = ldap_first_attribute(ld, ep, &cookie); ap != NULL; ap = ldap_next_attribute(ld, ep, cookie)) {
#ifdef DEBUG
if (debug & D_PARSE)
printf("parsing ap = %s\n", ap);
#endif
if ((idx = attr_to_index(ap)) < 0) {
printf(" Unknown attribute \"%s\"\n", ap);
continue;
}
add_value(&(Entry.attrs[idx]), ep, ap);
}
if( cookie != NULL ) {
ber_free( cookie, 0 );
}
}
#ifdef DEBUG
if (debug & D_PARSE)
printf(" Done parsing entry\n");
#endif
}
void
add_value( struct attribute *attr, LDAPMessage *ep, char *ap )
{
register int i = 0;
char **vp, **tp, **avp;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->add_value(%x, %x, %s)\n", attr, ep, ap);
#endif
vp = (char **) ldap_get_values(ld, ep, ap);
/*
* Fill in the attribute structure for this attribute. This
* stores away the values (using strdup()) and the count. Terminate
* the list with a NULL pointer.
*
* attr->quipu_name has already been set during initialization.
*/
if ((attr->number_of_values = ldap_count_values(vp)) > 0) {
attr->values = (char **) Malloc((unsigned) ((attr->number_of_values + 1) * sizeof(char *)));
avp = attr->values;
for (i = 1, tp = vp; *tp != NULL; i++, tp++) {
#ifdef DEBUG
if (debug & D_PARSE)
printf(" value #%d %s\n", i, *tp);
#endif
/*
* The 'name' field of the Entry structure already has
* has the first part of the DN copied into it. Thus,
* we don't need to save it away here again. Also, by
* tossing it away here, we make printing this info out
* a bit easier later.
*/
if (!strcmp(ap, "cn") && !strcmp(*tp, Entry.name)) {
attr->number_of_values--;
continue;
}
*avp++ = strdup(*tp);
}
*avp = NULL;
}
ldap_value_free(vp);
}
void
print_an_entry( void )
{
int n = 0, i, idx;
char is_a_group, **order;
char *sub_list[MAX_VALUES], buf[SMALL_BUF_SIZE];
#ifdef DEBUG
if (debug & D_TRACE)
printf("->print_an_entry()\n");
#endif
if( Entry.name == NULL ) {
printf(" No Entry found.\n");
return;
}
printf(" \"%s\"\n", Entry.name);
/*
* If the entry is a group, find all of the subscribers to that
* group. A subscriber is an entry that *points* to a group entry,
* and a member is an entry that is included as part of a group
* entry.
*
* We also need to select the appropriate output format here.
*/
is_a_group = isgroup();
if (is_a_group) {
order = (char **) group_attr_print_order;
n = find_all_subscribers(sub_list, Entry.DN);
#ifdef DEBUG
if (debug & D_PRINT)
printf(" Group \"%s\" has %d subscribers\n",
Entry.name, n);
#endif
}
else
order = (char **) person_attr_print_order;
for (i = 0; order[i] != NULL; i++) {
idx = attr_to_index(order[i]);
#ifdef DEBUG
if (debug & D_PRINT) {
printf(" ATTR #%2d = %s [%s] (%d values)\n", i + 1,
Entry.attrs[idx].output_string,
Entry.attrs[idx].quipu_name,
Entry.attrs[idx].number_of_values);
}
#endif
if (idx < 0)
continue;
if (Entry.attrs[idx].number_of_values == 0)
continue;
if (isadn(order[i]))
print_DN(Entry.attrs[idx]);
else if (isaurl(order[i]))
print_URL(Entry.attrs[idx]);
else if (isadate(order[i])) {
/* fix time and date, then call usual routine */
Entry.attrs[idx].values[0] =
time2text(Entry.attrs[idx].values[0], FALSE);
print_values(Entry.attrs[idx]);
}
else
print_values(Entry.attrs[idx]);
}
/*
* If it is a group, then we should print the subscriber list (if
* there are any). If there are a lot of them, prompt the user
* before printing them.
*/
if (is_a_group && (n > 0)) {
char *label = "Subscribers: ";
if (n > TOO_MANY_TO_PRINT) {
printf(" There are %d subscribers. Print them? ", n);
fflush(stdout);
fetch_buffer(buf, sizeof(buf), stdin);
if (!((buf[0] == 'y') || (buf[0] == 'Y')))
return;
}
format2((char *) my_ldap_dn2ufn(sub_list[n - 1]), label, (char *) NULL, 2,
2 + strlen(label) + 1, col_size);
for (n--; n > 0; n--)
format2((char *) my_ldap_dn2ufn(sub_list[n - 1]), (char *) NULL,
(char *) NULL, 2 + strlen(label),
2 + strlen(label) + 2, col_size);
}
return;
}
#define OUT_LABEL_LEN 20
/* prints the values associated with an attribute */
void
print_values( struct attribute A )
{
register int i, k;
register char *cp, **vp;
char out_buf[MED_BUF_SIZE], *padding = NULL;
int lead;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->print_values(%x)\n", A);
#endif
if (A.number_of_values == 0)
return;
if ((vp = A.values) == NULL)
return;
/*
* Pad out the output string label so that it fills the
* whole field of length OUT_LABEL_LEN.
*/
out_buf[0] = '\0';
i = OUT_LABEL_LEN - strlen(A.output_string);
if (i < 0) {
printf("Output string for \"%s\" is too long. Maximum length is %d characters\n", A.quipu_name, OUT_LABEL_LEN);
return;
}
if (isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values == 0)) {
A.output_string = "Members";
i = OUT_LABEL_LEN - strlen(A.output_string);
padding = (char *) Malloc((unsigned) (i + 1));
(void) memset(padding, ' ', i);
*(padding + i) = '\0';
sprintf(out_buf, "%s:%s", A.output_string, padding);
}
else if (!(isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values > 0))) {
padding = (char *) Malloc((unsigned) (i + 1));
(void) memset(padding, ' ', i);
*(padding + i) = '\0';
sprintf(out_buf, "%s:%s", A.output_string, padding);
}
/*
* If this happens to be a group, then do not print the output
* string if we have already printed out some members.
*/
else if (isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values > 0)) {
padding = (char *) Malloc((unsigned) (OUT_LABEL_LEN + 2));
(void) memset(padding, ' ', OUT_LABEL_LEN + 1);
*(padding + OUT_LABEL_LEN + 1) = '\0';
sprintf(out_buf, "%s", padding);
}
lead = strlen(out_buf) + 2;
printf(" %s", out_buf);
for (i = 0; *vp != NULL; i++, vp++) {
if (i > 0) {
if (!strncmp(A.output_string, "Home a", 6) || !strncmp(A.output_string, "Business a", 10)) {
printf(" %s", out_buf);
}
else {
for (k = lead; k > 0; k--)
putchar(' ');
}
}
for (cp = *vp; *cp != '\0'; cp++) {
switch (*cp) {
case '$' :
if (!strncmp(A.output_string, "Home a", 6) || !strncmp(A.output_string, "Business a", 10) || !strcmp(A.quipu_name, "multiLineDescription")) {
putchar('\n');
for (k = lead; k > 0; k--)
putchar(' ');
while (isspace((unsigned char) cp[1]))
cp++;
}
else
putchar(*cp);
break;
case '\n' :
putchar('%');
putchar('\n');
break;
default:
putchar(*cp);
}
}
putchar('\n');
}
if (padding != NULL)
Free(padding);
return;
}
/* prints the DN's associated with an attribute */
void
print_DN( struct attribute A )
{
int i, lead;
register char **vp;
char out_buf[MED_BUF_SIZE], *padding = NULL;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->print_DN(%x)\n", A);
#endif
if (A.number_of_values == 0)
return;
/*
* Pad out the output string label so that it fills the
* whole field of length OUT_LABEL_LEN.
*/
i = OUT_LABEL_LEN - strlen(A.output_string);
if (i > 0) {
padding = (char *) Malloc((unsigned) (i + 1));
(void) memset(padding, ' ', i);
*(padding + i) = '\0';
sprintf(out_buf, "%s:%s", A.output_string, padding);
(void) Free(padding);
}
lead = strlen(out_buf) + 2;
vp = A.values;
format2((char *) my_ldap_dn2ufn(*vp), out_buf, (char *) NULL, 2, lead + 1, col_size);
for (vp++; *vp != NULL; vp++) {
format2((char *) my_ldap_dn2ufn(*vp), (char *) NULL, (char *) NULL, lead,
lead + 1, col_size);
}
return;
}
void
clear_entry( void )
{
register int i;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->clear_entry()\n");
if ((debug & D_PRINT) && (Entry.name != NULL))
printf(" Clearing entry \"%s\"\n", Entry.name);
#endif
if (Entry.DN != NULL)
ldap_memfree(Entry.DN);
if (Entry.name != NULL)
Free(Entry.name);
Entry.may_join = FALSE;
Entry.subscriber_count = -1;
Entry.DN = Entry.name = NULL;
/* clear all of the values associated with all attributes */
for (i = 0; attrlist[i].quipu_name != NULL; i++) {
#ifdef DEBUG
if (debug & D_PRINT)
printf(" Clearing attribute \"%s\" -- ",
Entry.attrs[i].quipu_name);
#endif
if (Entry.attrs[i].values == NULL) {
#ifdef DEBUG
if (debug & D_PRINT)
printf(" no values, skipping\n");
#endif
continue;
}
#ifdef DEBUG
if (debug & D_PRINT)
printf(" freeing %d values\n",
Entry.attrs[i].number_of_values);
#endif
Entry.attrs[i].number_of_values = 0;
ldap_value_free(Entry.attrs[i].values);
Entry.attrs[i].values = (char **) NULL;
/*
* Note: We do not clear either of the char * fields
* since they will always be applicable.
*/
}
}
int
attr_to_index( char *s )
{
register int i;
for (i = 0; attrlist[i].quipu_name != NULL; i++)
if (!strcasecmp(s, attrlist[i].quipu_name))
return(i);
return(-1);
}
void
initialize_attribute_strings( void )
{
register int i;
for (i = 0; attrlist[i].quipu_name != NULL; i++)
Entry.attrs[i].quipu_name = attrlist[i].quipu_name;
for (i = 0; attrlist[i].quipu_name != NULL; i++)
Entry.attrs[i].output_string = attrlist[i].output_string;
}
/* prints the URL/label pairs associated with an attribute */
void
print_URL( struct attribute A )
{
int i, lead;
register char **vp;
char out_buf[MED_BUF_SIZE], *padding = NULL;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->print_URL(%x)\n", A);
#endif
if (A.number_of_values == 0)
return;
/*
* Pad out the output string label so that it fills the
* whole field of length OUT_LABEL_LEN.
*/
i = OUT_LABEL_LEN - strlen(A.output_string);
if (i > 0) {
padding = (char *) Malloc((unsigned) (i + 1));
(void) memset(padding, ' ', i);
*(padding + i) = '\0';
sprintf(out_buf, "%s:%s", A.output_string, padding);
}
lead = strlen(out_buf) + 2;
vp = A.values;
print_one_URL(*vp, 2, out_buf, lead);
for (vp++; *vp != NULL; vp++)
print_one_URL(*vp, lead, (char *) NULL, lead);
if (padding != NULL)
Free(padding);
return;
}
void
print_one_URL( char *s, int label_lead, char *tag, int url_lead )
{
register int i;
char c, *cp, *url;
for (cp = s; !isspace((unsigned char)*cp) && (*cp != '\0'); cp++)
;
c = *cp;
*cp = '\0';
url = strdup(s);
*cp = c;
if (*cp != '\0') {
for (cp++; isspace((unsigned char)*cp); cp++)
;
}
else
cp = "(no description available)";
format2(cp, tag, (char *) NULL, label_lead, label_lead + 1, col_size);
for (i = url_lead + 2; i > 0; i--)
printf(" ");
printf("%s\n", url);
Free(url);
}
#define GET2BYTENUM( p ) (( *(p) - '0' ) * 10 + ( *((p)+1) - '0' ))
static char *
time2text( char *ldtimestr, int dateonly )
{
struct tm t;
char *p, *timestr, zone, *fmterr = "badly formatted time";
time_t gmttime;
int ndigits;
if (strlen( ldtimestr ) < 12 ) {
return( fmterr );
}
for ( ndigits=0; isdigit((unsigned char) ldtimestr[ndigits]); ndigits++) {
; /* EMPTY */
}
if ( ndigits != 12 && ndigits != 14) {
return( fmterr );
}
memset( (char *)&t, '\0', sizeof( struct tm ));
p = ldtimestr;
if( ndigits == 14) {
/* came with a century */
/* POSIX says tm_year should be year - 1900 */
t.tm_year = 100 * GET2BYTENUM( p ) - 1900;
p += 2;
} else {
t.tm_year = 0;
}
t.tm_year += GET2BYTENUM( p ); p += 2;
t.tm_mon = GET2BYTENUM( p ) - 1; p += 2;
t.tm_mday = GET2BYTENUM( p ); p += 2;
t.tm_hour = GET2BYTENUM( p ); p += 2;
t.tm_min = GET2BYTENUM( p ); p += 2;
t.tm_sec = GET2BYTENUM( p ); p += 2;
if (( zone = *p ) == 'Z' ) { /* GMT */
zone = '\0'; /* no need to indicate on screen, so we make it null */
}
gmttime = gtime( &t );
timestr = ctime( &gmttime );
timestr[ strlen( timestr ) - 1 ] = zone; /* replace trailing newline */
if ( dateonly ) {
AC_MEMCPY( timestr + 11, timestr + 20, strlen( timestr + 20 ) + 1 );
}
return( strdup( timestr ) );
}
/* gtime.c - inverse gmtime */
#include <ac/time.h>
/* gtime(): the inverse of localtime().
This routine was supplied by Mike Accetta at CMU many years ago.
*/
int dmsize[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
#define dysize(y) \
(((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
/*
* Y2K YEAR
*/
/* per STDC & POSIX tm_year *should* be offset by 1900 */
#define YEAR_POSIX(y) ((y) + 1900)
/*
* year is < 1900, year is offset by 1900
*/
#define YEAR_CAREFUL(y) ((y) < 1900 ? (y) + 1900 : (y))
#define YEAR(y) YEAR_CAREFUL(y)
/* */
static long
gtime( struct tm *tm )
{
register int i,
sec,
mins,
hour,
mday,
mon,
year;
register long result;
if ((sec = tm -> tm_sec) < 0 || sec > 59
|| (mins = tm -> tm_min) < 0 || mins > 59
|| (hour = tm -> tm_hour) < 0 || hour > 24
|| (mday = tm -> tm_mday) < 1 || mday > 31
|| (mon = tm -> tm_mon + 1) < 1 || mon > 12)
return ((long) -1);
if (hour == 24) {
hour = 0;
mday++;
}
year = YEAR (tm -> tm_year);
result = 0L;
for (i = 1970; i < year; i++)
result += dysize (i);
if (dysize (year) == 366 && mon >= 3)
result++;
while (--mon)
result += dmsize[mon - 1];
result += mday - 1;
result = 24 * result + hour;
result = 60 * result + mins;
result = 60 * result + sec;
return result;
}

View File

@ -1,184 +0,0 @@
# Microsoft Developer Studio Project File - Name="ud" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=ud - Win32 Single Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ud.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ud.mak" CFG="ud - Win32 Single Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ud - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "ud - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "ud - Win32 Single Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "ud - Win32 Single Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "ud - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\..\Release"
# PROP Intermediate_Dir "..\..\Release\ud"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib hs_regex.lib sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Release"
!ELSEIF "$(CFG)" == "ud - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\..\Debug"
# PROP Intermediate_Dir "..\..\Debug\ud"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib hs_regex.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Debug"
!ELSEIF "$(CFG)" == "ud - Win32 Single Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "ud___Wi0"
# PROP BASE Intermediate_Dir "ud___Wi0"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\..\SRelease"
# PROP Intermediate_Dir "..\..\SRelease\ud"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib ws2_32.lib hs_regex.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\libraries\Release"
# ADD LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib hs_regex.lib sasl.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\SRelease"
!ELSEIF "$(CFG)" == "ud - Win32 Single Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "ud___Wi1"
# PROP BASE Intermediate_Dir "ud___Wi1"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\..\SDebug"
# PROP Intermediate_Dir "..\..\SDebug\ud"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib ws2_32.lib hs_regex.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libraries\Debug"
# ADD LINK32 oldap32.lib olber32.lib oldif32.lib olutil32.lib hs_regex.lib libsasl.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\SDebug"
!ENDIF
# Begin Target
# Name "ud - Win32 Release"
# Name "ud - Win32 Debug"
# Name "ud - Win32 Single Release"
# Name "ud - Win32 Single Debug"
# Begin Source File
SOURCE=.\auth.c
# End Source File
# Begin Source File
SOURCE=.\edit.c
# End Source File
# Begin Source File
SOURCE=.\find.c
# End Source File
# Begin Source File
SOURCE=.\globals.c
# End Source File
# Begin Source File
SOURCE=.\group.c
# End Source File
# Begin Source File
SOURCE=.\help.c
# End Source File
# Begin Source File
SOURCE=.\main.c
# End Source File
# Begin Source File
SOURCE=.\mod.c
# End Source File
# Begin Source File
SOURCE=.\print.c
# End Source File
# Begin Source File
SOURCE=.\ud.h
# End Source File
# Begin Source File
SOURCE=.\util.c
# End Source File
# End Target
# End Project

View File

@ -1,277 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 1991, 1992, 1993
* 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.
*/
#define MAX_VALUES 1000
/*****************************************************************************
**
** Limits which ud imposes. Also subject to change.
**
*****************************************************************************/
/*
* Names are parsed somewhat like 'awk' parses them. This is the
* maximum number of components we store away.
*
* The isnamesepartor() macro should return TRUE if x is equal to one of the
* characters that delimits name fields. The ignorechar() macro should
* return TRUE if it is equal to a character that should be ignored when
* parsing names.
*/
#define MAX_NAME_COMPS 8
#define isnamesepartor(x) (isspace((unsigned char) (x)))
#define isignorechar(x) (((x) == '.') || ((x) == '_'))
/*
* Quite often a search will turn up more than one match. When it does we
* print out a list of the matches, and ask the user to select the one that
* s/he wants. This defines how many we will save and show.
*/
#define MAX_NUM_NAMES 128
/*
* When a user displays a group, we will automatically print out this many
* members and subscribers. If the number is greater than this, we will
* prompt the user before printing them.
*/
#define TOO_MANY_TO_PRINT 16
/*
* This is the default size of a tty if we can't figure out the actual size.
*/
#define DEFAULT_TTY_HEIGHT 24
#define DEFAULT_TTY_WIDTH 80
/*
* The number of attributes we know about must be less than this number.
* Don't add lots of attributes to the list in globals.c without checking
* this number too.
*/
#define MAX_ATTRS 64
/*****************************************************************************
**
** No user servicable parts beyond this point.
**
*****************************************************************************/
/*
* Generic buffer sizes.
*/
#define SMALL_BUF_SIZE 16
#define MED_BUF_SIZE 128
#define LARGE_BUF_SIZE 512
/*
* Used to specify the operation in x_group().
*/
#define G_JOIN 0
#define G_RESIGN 1
/*
* TRUE and FALSE - just in case we need them.
*/
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
/*
* Bound status.
*/
#define UD_NOT_BOUND 0 /* bound only as the default defined above */
#define UD_BOUND 1 /* bound as an actual Directory entity */
/*
* Debug masks.
*/
#define D_TRACE 0x0001
#define D_FIND 0x0002
#define D_GROUPS 0x0004
#define D_MODIFY 0x0008
#define D_PARSE 0x0010
#define D_PRINT 0x0020
#define D_AUTHENTICAT 0x0040
#define D_INITIALIZE 0x0080
/*
* Used in the flags field of an attribute structure.
*/
#define ATTR_FLAG_NONE 0x0000
#define ATTR_FLAG_PERSON 0x0001
#define ATTR_FLAG_GROUP 0x0002
#define ATTR_FLAG_PERSON_MOD 0x0010
#define ATTR_FLAG_GROUP_MOD 0x0020
#define ATTR_FLAG_MAY_EDIT 0x0040
#define ATTR_FLAG_SEARCH 0x0100
#define ATTR_FLAG_READ 0x0200
#define ATTR_FLAG_IS_A_DATE 0x0800
#define ATTR_FLAG_IS_A_DN 0x1000
#define ATTR_FLAG_IS_A_URL 0x2000
#define ATTR_FLAG_IS_A_BOOL 0x4000
#define ATTR_FLAG_IS_MULTILINE 0x8000
LDAP_BEGIN_DECL
/*
* These are the structures we use when parsing an answer we get from the LDAP
* server.
*/
struct attribute {
char *quipu_name;
char *output_string;
void (*mod_func) LDAP_P(( char *who, int attr_idx ));
unsigned short flags;
int number_of_values;
char **values;
};
struct entry {
char may_join;
int subscriber_count;
char *DN;
char *name;
struct attribute attrs[MAX_ATTRS];
};
/*
* Variables
*/
/* in globals.c: */
extern struct attribute attrlist[];/* complete list of attrs */
/* in main.c: */
extern char copyright[];
extern char *default_bind_object;
extern char *bound_dn;
extern char *group_base;
extern char *search_base; /* search base */
extern int lpp;
extern int verbose; /* verbose mode flag */
extern int col_size;
extern int bind_status;
extern LDAP *ld; /* our ldap descriptor */
extern LDAPFiltDesc *lfdp; /* LDAP filter descriptor */
#ifdef DEBUG
extern int debug; /* debug flag */
#endif
/* in print.c: */
extern struct entry Entry;
extern int dmsize[];
/* in version.c: */
extern char Version[];
/*
* Functions
*/
/* in auth.c: */
int auth LDAP_P(( char *who, int implicit ));
/* in edit.c: */
void edit LDAP_P(( char *who ));
/* in find.c: */
int vrfy LDAP_P(( char *dn ));
LDAPMessage *find LDAP_P(( char *who, int quiet ));
int pick_one LDAP_P(( int i ));
void print_list LDAP_P(( LDAPMessage *list, char **names, int *matches ));
int find_all_subscribers LDAP_P(( char **sub, char *group ));
char *fetch_boolean_value LDAP_P(( char *who, struct attribute attr ));
/* in globals.c: */
/* in group.c: */
void add_group LDAP_P(( char *name ));
void remove_group LDAP_P(( char *name ));
void x_group LDAP_P(( int action, char *name ));
void bulk_load LDAP_P(( char *group ));
void purge_group LDAP_P(( char *group ));
void tidy_up LDAP_P(( void ));
void mod_addrDN LDAP_P(( char *group, int offset ));
int my_ldap_modify_s LDAP_P(( LDAP *ldap, char *group, LDAPMod **mods ));
void list_groups LDAP_P(( char *who ));
void list_memberships LDAP_P(( char *who ));
/* in help.c: */
void print_help LDAP_P(( char *s ));
/* in main.c: */
#ifdef DEBUG
#endif
void do_commands LDAP_P(( void )) LDAP_GCCATTR((noreturn));
void status LDAP_P(( void ));
void change_base LDAP_P(( int type, char **base, char *s ));
void initialize_client LDAP_P(( void ));
RETSIGTYPE attn LDAP_P(( int sig ));
#if !defined(NO_TERMCAP) && defined(TIOCGWINSZ)
RETSIGTYPE chwinsz LDAP_P(( int sig ));
#endif
/* in mod.c: */
void modify LDAP_P(( char *who ));
void change_field LDAP_P(( char *who, int attr_idx ));
char *get_value LDAP_P(( char *id, char *prompt ));
void set_boolean LDAP_P(( char *who, int attr_idx ));
#ifdef UOFM
void set_updates LDAP_P(( char *who, int dummy ));
#endif
void print_mod_list LDAP_P(( int group ));
int perform_action LDAP_P(( char *choice, char *dn, int group ));
void mod_perror LDAP_P(( LDAP *ld ));
/* in print.c: */
void parse_answer LDAP_P(( LDAPMessage *s ));
void add_value LDAP_P(( struct attribute *attr, LDAPMessage *ep, char *ap ));
void print_an_entry LDAP_P(( void ));
void print_values LDAP_P(( struct attribute A ));
void print_DN LDAP_P(( struct attribute A ));
void clear_entry LDAP_P(( void ));
int attr_to_index LDAP_P(( char *s ));
void initialize_attribute_strings LDAP_P(( void ));
void print_URL LDAP_P(( struct attribute A ));
void print_one_URL LDAP_P(( char *s, int l_lead, char *tag, int u_lead ));
/* in util.c: */
void printbase LDAP_P(( char *lead, char *s ));
void fetch_buffer LDAP_P(( char *buffer, int length, FILE *where ));
void fatal LDAP_P(( char *s )) LDAP_GCCATTR((noreturn));
int isgroup LDAP_P(( void ));
void format LDAP_P(( char *str, int width, int lead ));
void format2 LDAP_P(( char *s, char *ft, char *t, int fi, int i, int w ));
char *strip_ignore_chars LDAP_P(( char *cp ));
char *code_to_str LDAP_P(( int i ));
char *friendly_name LDAP_P(( char *s ));
#ifdef UOFM
int isauniqname LDAP_P(( char *s ));
#endif
int isadn LDAP_P(( char *s ));
char *my_ldap_dn2ufn LDAP_P(( char *s ));
int isaurl LDAP_P(( char *s ));
int isadate LDAP_P(( char *s ));
void *Malloc LDAP_P(( unsigned int size ));
void Free LDAP_P(( void *ptr ));
char *nextstr LDAP_P(( char *s ));
void free_mod_struct LDAP_P(( LDAPMod *modp ));
void StrFreeDup LDAP_P(( char **ptr, char *new_value ));
int confirm_action LDAP_P(( char *msg ));
LDAP_END_DECL

View File

@ -1,499 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* Copyright (c) 1992, 1993 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/stdlib.h>
#include <ac/ctype.h>
#include <ac/errno.h>
#include <ac/signal.h>
#include <ac/string.h>
#include <ac/termios.h>
#include <ac/time.h>
#include <ac/unistd.h>
#include <ldap.h>
#include "ldap_defaults.h"
#include "ud.h"
void
printbase( char *lead, char *s )
{
#ifdef DEBUG
if (debug & D_TRACE)
printf("->printbase(%s, %s)\n", lead, s);
#endif
if (lead == NULL) {
printf("root\n");
return;
}
if (s == NULL) {
printf("%sroot\n", lead);
return;
}
printf("%s%s\n", lead, s);
return;
}
void
fetch_buffer( char *buffer, int length, FILE *where )
{
register int i;
char *p;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->fetch_buffer(%x, %d, %x)\n", buffer, length, where);
#endif
/*
* Fetch a buffer and strip off any leading or trailing non-printing
* characters, namely newlines and carriage returns.
*/
if (fgets(buffer, length, where) == NULL) {
if (feof(where))
errno = 0; /* so fatal() doesn't bitch */
fatal("fgets");
}
for (i = strlen(buffer) - 1;
i >= 0 && !isprint((unsigned char) buffer[i]); i--)
buffer[i] = '\0';
p = buffer;
while ( *p != '\0' ) {
if ( isprint( (unsigned char) *p )) {
++p;
} else {
AC_MEMCPY( p, p + 1, strlen( p + 1 ) + 1 );
}
}
}
void
fatal( char *s )
{
if (errno != 0)
perror(s);
exit( EXIT_FAILURE );
}
int
isgroup( void )
{
char **vp;
register int i;
int group = FALSE;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->isgroup()\n");
#endif
if ((i = attr_to_index("objectClass")) == -1)
return(FALSE);
vp = Entry.attrs[i].values;
for (i = 0; *vp != NULL; vp++) {
#ifdef DEBUG
i++;
if (debug & D_GROUPS)
printf("class #%1d: (%s)\n", i, *vp);
#endif
if (!strcmp(*vp, "rfc822MailGroup"))
group = TRUE;
}
return(group);
}
/*
* Print out the string 's' on a field of 'width' chracters. Each line
* should be indented 'lead' characters.
*/
void
format( char *str, int width, int lead )
{
char *s, *original, *leader = "";
register char *cp;
#ifdef DEBUG
if (debug & D_TRACE)
printf("->format(%s, %d, %d)\n", str, width, lead);
#endif
if (lead >= width) {
fprintf(stderr, " Cannot format (%s, %d, %d)\n", str, width, lead);
return;
}
if (lead > 0) {
leader = (char *) Malloc((unsigned) (lead + 1));
(void) memset(leader, ' ', lead);
*(leader + lead) = '\0';
}
/*
* Some compilers get really unhappy with this function since it
* fiddles around with the first argument, which could be a string
* constant. We do a strdup() here so we can do whatever the hell
* we want.
*/
s = original = strdup(str);
for (;;) {
if (((int) strlen(s) + lead) < width) {
printf("%s%s\n", leader, s);
Free(leader);
Free(original);
return;
/*NOTREACHED*/
}
cp = s + width - lead;
while (!isspace((unsigned char)*cp) && (cp != s))
cp--;
*cp = '\0';
while (isspace((unsigned char)*s))
s++;
printf("%s%s\n", leader, s);
s = cp + 1;
}
}
/*
* Print out the string 's' on a field of 'width' chracters. The first line
* should be indented 'first_indent' spaces, then followed by 'first_tag',
* and then followed by the first line of 's'. Subsequent lines should be
* indented 'indent' spaces, then followed by 'tag', and then followed by
* subsequent lines of 's'.
*/
void
format2(
char *s,
char *first_tag,
char *tag,
int first_indent,
int indent,
int width
)
{
char c, *fi, *i;
register char *cp;
if (first_tag == NULL)
first_tag = "";
if (tag == NULL)
tag = "";
#ifdef DEBUG
if (debug & D_TRACE)
printf("format2(\"%s\", \"%s\", \"%s\", %1d, %1d, %1d)\n", s,
first_tag, tag, first_indent, indent, width);
#endif
/* make sure the indents are sane */
if ((first_indent >= width) || (indent >= width)) {
fprintf(stderr, " Cannot format: indent too large\n");
return;
}
/* make the indentations */
if (first_indent > 0) {
fi = (char *) Malloc((unsigned) (first_indent + 1));
(void) memset(fi, ' ', first_indent);
*(fi + first_indent) = '\0';
}
else
fi = "";
if (indent > 0) {
i = (char *) Malloc((unsigned) (indent + 1));
(void) memset(i, ' ', indent);
*(i + indent) = '\0';
}
else
i = "";
/* now do the first line */
if (((int) strlen(s) + (int) strlen(first_tag) + first_indent) < width) {
printf("%s%s%s\n", fi, first_tag, s);
Free(fi);
Free(i);
return;
/*NOTREACHED*/
}
/*
* 's' points to the beginning of the string we want to print.
* We point 'cp' to the end of the maximum amount of text we
* can print (i.e., total width less the indentation and the
* length of the tag). Once we have set 'cp' initially we
* back it up to the first space character.
*/
cp = s + width - first_indent - strlen(first_tag);
while (!isspace((unsigned char)*cp) && (cp != s))
cp--;
/*
* Once there, we change that space character to a null, print the
* string, and then restore the space character.
*/
c = *cp;
*cp = '\0';
printf("%s%s%s\n", fi, first_tag, s);
*cp = c;
/*
* Since 'cp' may have been set to a space initially (and so no
* back-tracking was performed), it could have a space after it
* as well. We should gobble up all of these since we don't want
* unexpected leading blanks.
*/
for (s = cp + 1; isspace((unsigned char)*s); s++)
;
/* now do all of the other lines */
for (;;) {
if (((int) strlen(s) + (int) strlen(tag) + indent) < width) {
printf("%s%s%s\n", i, tag, s);
Free(fi);
Free(i);
return;
/*NOTREACHED*/
}
cp = s + width - indent - strlen(tag);
while (!isspace((unsigned char)*cp) && (cp != s))
cp--;
c = *cp;
*cp = '\0';
printf("%s%s%s\n", i, tag, s);
s = cp + 1;
*cp = c; /* don't mess up 's' */
}
}
#define IN_A_QUOTE 0
#define OUT_OF_QUOTE 1
char *
strip_ignore_chars( char *cp )
{
int had_a_comma = FALSE;
int flag = OUT_OF_QUOTE;
register char *rcp, *cp1;
char *tmp;
#ifdef DEBUG
if (debug & D_TRACE)
printf("strip_ignore_chars(%s)\n", cp);
#endif
for (rcp = cp; *rcp != '\0'; rcp++)
if (isignorechar(*rcp) || (*rcp == '"'))
break;
if (*rcp == '\0')
return(cp);
cp1 = tmp = (char *) Malloc((unsigned) strlen(cp));
for (rcp = cp; *rcp != '\0'; rcp++) {
/* toss quotes and flip the flag */
if (*rcp == '"')
flag = OUT_OF_QUOTE - flag;
else if (isignorechar(*rcp)) {
if (flag == OUT_OF_QUOTE)
*cp1++ = ' ';
else
*cp1++ = *rcp;
}
else if (*rcp == ',') {
*cp1++ = *rcp;
had_a_comma = TRUE;
}
else
*cp1++ = *rcp;
}
*cp1 = '\0';
/* re-quote the name if it had a comma in it */
if (had_a_comma == TRUE) {
rcp = cp1 = (char *) Malloc((unsigned) (strlen(tmp) + 3));
*rcp++ = '"';
*rcp = '\0';
strcat(rcp, tmp);
strcat(rcp, "\"");
Free(tmp);
tmp = cp1;
}
return(tmp);
}
char *
code_to_str( int i )
{
switch(i) {
case LDAP_MOD_ADD : return("ADD");
case LDAP_MOD_DELETE : return("DELETE");
case LDAP_MOD_REPLACE : return("REPLACE");
default : return("?????");
}
}
#ifdef UOFM
/* return TRUE if s has the syntax of a uniqname */
int
isauniqname( char *s )
{
int i = strlen(s);
if ((i < 3) || (i > 8)) /* uniqnames are 3-8 chars */
return(FALSE);
if (!isalpha((unsigned char)*s)) /* uniqnames begin with a letter */
return(FALSE);
for ( ; *s != '\0'; s++) /* uniqnames are alphanumeric */
if (!isalnum((unsigned char)*s))
return(FALSE);
return(TRUE);
}
#endif
/* return TRUE if this attribute should be printed as a DN */
int
isadn( char *s )
{
register int i;
for (i = 0; attrlist[i].quipu_name != NULL; i++)
if (!strcasecmp(s, attrlist[i].quipu_name))
break;
if (attrlist[i].flags & ATTR_FLAG_IS_A_DN)
return(TRUE);
return(FALSE);
}
char *
my_ldap_dn2ufn( char *s )
{
#ifdef UD_BASE
register char **cpp;
static char short_DN[BUFSIZ];
if (strstr(s, UD_BASE) == NULL)
return(ldap_dn2ufn(s));
cpp = ldap_explode_dn(s, TRUE);
sprintf(short_DN, "%s, %s", *cpp, *(cpp + 1));
ldap_value_free(cpp);
return(short_DN);
#else
return(ldap_dn2ufn(s));
#endif
}
/* return TRUE if this attribute should be printed as a URL */
int
isaurl( char *s )
{
register int i;
for (i = 0; attrlist[i].quipu_name != NULL; i++)
if (!strcasecmp(s, attrlist[i].quipu_name))
break;
if (attrlist[i].flags & ATTR_FLAG_IS_A_URL)
return(TRUE);
return(FALSE);
}
/* return TRUE if this attribute should be printed as a date and time */
int
isadate( char *s )
{
register int i;
for (i = 0; attrlist[i].quipu_name != NULL; i++)
if (!strcasecmp(s, attrlist[i].quipu_name))
break;
if (attrlist[i].flags & ATTR_FLAG_IS_A_DATE)
return(TRUE);
return(FALSE);
}
void *
Malloc( unsigned int size )
{
void *void_ptr;
void_ptr = (void *) malloc(size);
if (void_ptr == NULL) {
perror("malloc");
exit( EXIT_FAILURE );
/*NOTREACHED*/
}
return(void_ptr);
}
void
Free( void *ptr )
{
free(ptr);
}
char *
nextstr( char *s )
{
while (isspace((unsigned char) *s) && (*s != '\0'))
s++;
if (s == NULL)
return(NULL);
if (*s == '\0')
return(NULL);
return(s);
}
void
free_mod_struct( LDAPMod *modp )
{
if (modp->mod_values != NULL)
(void) ldap_value_free(modp->mod_values);
Free(modp->mod_type);
Free(modp);
}
void
StrFreeDup( char **ptr, char *new_value )
{
if (*ptr != NULL)
Free(*ptr);
if (new_value == NULL)
*ptr = NULL;
else
*ptr = strdup(new_value);
}
int
confirm_action( char *msg )
{
char tmp[SMALL_BUF_SIZE];
int i;
if ( msg != NULL ) {
putchar( '\n' );
format( msg, 75, 2 );
}
printf("\n Is this OK? ");
fflush(stdout);
tmp[0] = '\0';
fetch_buffer(tmp, sizeof(tmp), stdin);
i = strlen(tmp);
return( i > 0 &&
( !strncasecmp(tmp, "YES", i) || !strncasecmp(tmp, "OK", i)));
}

View File

@ -2830,9 +2830,6 @@ doc/man/man3/Makefile:build/top.mk:doc/man/man3/Makefile.in:build/man.mk \
doc/man/man5/Makefile:build/top.mk:doc/man/man5/Makefile.in:build/man.mk \
doc/man/man8/Makefile:build/top.mk:doc/man/man8/Makefile.in:build/man.mk \
clients/Makefile:build/top.mk:clients/Makefile.in:build/dir.mk \
clients/mail500/Makefile:build/top.mk:clients/mail500/Makefile.in:build/rules.mk \
clients/ud/Makefile:build/top.mk:clients/ud/Makefile.in:build/rules.mk \
clients/maildap/Makefile:build/top.mk:clients/maildap/Makefile.in:build/rules.mk \
clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk \
include/Makefile:build/top.mk:include/Makefile.in \
libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk \

View File

@ -1,89 +0,0 @@
.TH UD 1 "RELEASEDATE" "OpenLDAP LDVERSION"
.\" $OpenLDAP$
.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.UC 6
.SH NAME
ud \- interactive LDAP Directory Server query program
.SH SYNOPSIS
.B ud
[\c
.BR -Dv ]
.RB [ -s
.IR server ]
.RB [ -d
.IR debug-mask ]
.RB [ -l
.IR ldap-debug-mask ]
.RB [ -f
.IR file ]
.SH DESCRIPTION
.IR ud
is used to interogate a directory server via the Lightweight Directory
Access Protocol (LDAP).
.SH OPTIONS
.TP 1i
.BI \-s \ server
Used to specify the name of an LDAP server to which
.B ud
should connect. If this
flag is omitted, the value specified in the
.B ud
configuration file is used. If
no value is specified in the configuration file, or the configuration
file does not exist, the name
.IR ldap
is used. Of course, it is up to the system administrator to make sure that
the name
.IR ldap
can be resolved (presumably through the use of a CNAME or A record in the DNS
and the appropriate search path specified in the resolver config file).
.TP 1i
.BI \-d \ debug-mask
Sets the
.B ud
debug mask to the value specified.
Values for the mask can be dumped by using the
.IR \-D
flag.
.TP 1i
.BI \-f \ file
Sets the configuration file to the name specified.
.TP 1i
.BI \-l \ ldap-debug-mask
Sets the LDAP debug mask to the value specified.
.TP 1i
.B \-v
Turns on verbose output. Also toggable via the ud
.IR verbose
command.
.TP 1i
.B \-D
Prints out a list of valid ud debug masks.
.SH FILES
.TP
.I ETCDIR/ud.conf
system-wide ud configuration file
.TP
.I $HOME/.udrc
personal ud configuration file, overriding system file
.SH "SEE ALSO"
.BR ud.conf (5),
.BR ldap.conf (5),
.BR ldap (3)
.SH DIAGNOSTICS
.B ud
will try to be nice about error conditions, and in most cases prints a warm
and fuzzy error message when it encounters a problem. Sometimes the error
will be unexpected, and in these cases,
.B ud
uses the ldap_perror() routine to print an informative diagnostic.
.SH BUGS
Too numerous to mention.
.SH AUTHOR
Bryan Beecher, University of Michigan
.SH ACKNOWLEDGEMENTS
.B OpenLDAP
is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
.B OpenLDAP
is derived from University of Michigan LDAP 3.3 Release.

View File

@ -1,109 +0,0 @@
.TH UD.CONF 5 "RELEASEDATE" "OpenLDAP LDVERSION"
.\" $OpenLDAP$
.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.UC 6
.SH NAME
ud.conf \- ud configuration file
.SH SYNOPSIS
ETCDIR/ud.conf
.SH DESCRIPTION
The
.I ud
configuration file is used to set system-wide defaults to be applied when
running
.IR ud .
Note that each user may specify an optional configuration file,
.IR .udrc ,
in his/her home directory which will be used instead of the system-wide
configuration file.
.SH OPTIONS
The different configuration options are:
.TP 1i
\fBHOST <name>\fP
Used to specify the name of an LDAP server to which
.I ud
should connect. There may be only one entry per config file.
The server's name can be specified as a domain-style name or an IP address.
.TP 1i
\fBBASE <base>\fP
Used to specify the search base to use when performing search operations.
The base may be changed by those using
.I ud
by using the
.I cb
command.
There may be only one entry per config file.
The base must be specified as a Distinguished Name in LDAP format.
.TP 1i
\fBGROUPBASE <base>\fP
Used to specify the base used when creating groups.
The base may be changed by those using
.I ud
by using the
.I changegroup
command.
There may be only one entry per config file.
The base must be specified as a Distinguished Name in LDAP format.
.TP 1i
\fBSEARCH <algorithm>\fP
Used to specify a search algorithm to use when performing searches. More than
one algorithm may be specified, and each is tried in turn until a suitable
response is found.
Each algorithm specifies a filter that should be used when performing a find
operation. Filters contain LDAP-style attribute types (e.g., uid, cn,
postalAddress)
and operators to test for equality or approximate equality. Prefix operators
may also be used to specify AND, OR and NOT operations (see ldap(3) for
more details on the filter format). Algorithms use a
compile-time constant as a separator to use when parsing the input the user
has provided. This parsed input can then be referenced similarly to an
.I awk
program using symbols like $1, $2, and $0 for the entire batch of input.
For example, the algoritm
.I cn=$0
causes
.I ud
to perform a lookup on the entire string the user has typed, searching for
anything where the commonName exactly matches the whole thing.
Another example,
.I sn~=$NF
causes
.I ud
to do a search where the last element the user has typed (NF = number of fields
and is a special "number" that can be used in
.I awk
as well as
.IR ud )
searching for any matches that approximately match Surname.
Search algorithms also support a special feature which allows one to specify
the
.I exact
number of fields that must be present in order for the algorithm to be
applied. This number must be specified between square brackets.
For example,
.I [1] uid=$1
causes this algorithm to be applied when the number of fields is exactly equal
to one. If there is exactly one field, the token is looked up as a UID.
.SH FILES
.TP
.I ETCDIR/ud.conf
system-wide ud configuration file
.TP
.I $HOME/.udrc
personal ud configuration file, overriding system file
.SH "SEE ALSO"
.BR ud (1),
.BR ldap (3)
.SH AUTHOR
Bryan Beecher, University of Michigan
.SH ACKNOWLEDGEMENTS
.B OpenLDAP
is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
.B OpenLDAP
is derived from University of Michigan LDAP 3.3 Release.

View File

@ -1,295 +0,0 @@
.TH MAIL500 8C "RELEASEDATE" "OpenLDAP LDVERSION"
.\" $OpenLDAP$
.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.SH NAME
mail500 \- X.500 capable mailer
.LP
fax500 \- X.500 capable fax delivery agent
.SH SYNOPSIS
.B LIBEXECDIR/mail500 [\-d level] [\-f mailfrom]
.B [\-h hostname] [\-l ldaphost]
.B [\-m address] [\-v vacationhost]
.LP
.B LIBEXECDIR/fax500 [\-d level] [\-f mailfrom]
.B [\-h hostname] [\-l ldaphost]
.B [\-m address]
.SH DESCRIPTION
.B mail500
is an LDAP/X.500-capable mailer, suitable to be invoked from a
mail delivery agent such as
.BR sendmail (8).
It supports mail to both individuals and groups.
.B fax500
is an LDAP/X.500-capable facsimile delivery agent. It utilizes the
Internet remote-printing experiment (tpc.int). For more
information on tpc.int, look in
.B /mrose/tpc
on
.BR ftp.ics.uci.edu ,
or send mail to
.BR tpc-faq@town.hall.org .
.SH OPTIONS
.RB \- d level
Turn on debugging as defined by
.I level.
This option directs
.B mail500/fax500
to produce various debugging output via the
.BR syslog (8)
facility at the LOG_ALERT level.
.TP
.BI \-f " mailfrom"
This option tells
.B mail500/fax500
what to set the envelop from address to when (re)invoking sendmail
to deliver mail.
.I mailfrom
should be a valid email address. Normally, this option is passed
to
.B mail500/fax500
via the sendmail.cf(5) mailer definition, and is set
to something like the $f macro.
.TP
.BI \-l " ldaphost"
Specify an alternate host on which the LDAP server is running.
.TP
.BI \-m " address"
If
.I mail500/fax500
produces a rejection message, this is the
.I address
from which it will com. Normally, this option is passed to
.I mail500/fax500
via the sendmail.cf(5) mailer definition, and is set to something
like $n@$w (typically, mailer-daemon@hostname).
.TP
.BI \-v " vacationhost"
If the vacation facility is operative, this option specifies the
host to which the mail of users who are on vacation should be sent.
.SH HOW MAIL500 AND FAX500 WORK
When mail500/fax500 gets invoked with one or more names to which to
deliver mail, it searches for each name in X.500. Where it searches,
and what kind(s) of search(es) it does are compile-time configurable
by changing the
.B base
array in
.BR main.c .
For example, the configuration we use at U-M is like this:
.LP
.nf
Base base[] =
{ "ou=People, o=University of Michigan, c=US", 0
"uid=%s", "cn=%s", NULL,
"ou=System Groups, ou=Groups, o=University of Michigan, c=US", 1
"(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
"ou=User Groups, ou=Groups, o=University of Michigan, c=US", 1
"(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
NULL
};
.fi
.LP
which means that in delivering mail to "name@umich.edu"
.B mail500/fax500would do the
the following searches, stopping if it finds a match at any step:
.LP
.nf
subtree search of "ou=People, o=University of Michigan, c=US"
for (uid=name)
subtree search of "ou=People, o=University of Michigan, c=US"
for (cn=name)
subtree search of "ou=System Groups, ou=Groups, o=University of Michigan, c=US"
for (&(cn=name)(associatedDomain=umich.edu))
subtree search of "ou=User Groups, ou=Groups, o=University of Michigan, c=US"
for (&(cn=name)(associatedDomain=umich.edu))
.fi
.LP
Notice that when specifying a filter %s is replaced by the name,
or user portion of the address while %h is replaced by whatever is
passed in to
.B mail500/fax500
via the
.RB \- h
option (typically the host portion of the address).
.LP
You can also specify whether you want search results that matched
because the entry's RDN matched the search to be given preference
or not. At U-M, we only give such preference in the mail group
portion of the searches. Beware with this option: the algorithm
used to decide whether an entry's RDN matched the search is very
simple-minded, and may not always be correct.
.LP
There is currently no limit on the number of areas searched (the base
array can be as large as you want), and an arbitrary limit of 2 filters
for each base. If you want more than that, simply changing the 3 in
the typedef for Base should do the trick.
.SH X.500 SUPPORT
In X.500, there are several new attribute types and one new object
class defined that
.B mail500/fax500
uses. At its most basic, for normal
entries
.B mail500
will deliver to the value(s) listed in the
.B mail
attribute of the entry, and
.B fax500
will attempt to deliver a fax to the telephone number listed in the
.B facsimileTelephoneNumber
attribute. For example, at U-M my entry has the attribute
.LP
.nf
mail= tim@terminator.rs.itd.umich.edu
.fi
.LP
So mail sent to tim@umich.edu will be delivered via
.B mail500
to that
address (assuming the
.BR sendmail.cf (5)
file is set up to call
.B mail500
for mail to somebody@umich.edu - see below). If there were multiple
values for the mail attribute, multiple copies of the mail would be sent.
.LP
In the case of
.BR fax500 , if my entry has the attribute
.LP
.nf
facsimileTelephoneNumber= +1 313 764 5140
.fi
.LP
A message sent to tim@fax.umich.edu (assuming the sendmail.cf file
is set up to pass mail @fax.umich.edu to
.BR fax500 \-
see below)
will generate a message to
remote-printer.Timothy_A_Howes@0.4.1.5.4.6.7.3.1.3.1.tpc.int.
.LP
A new object class, rfc822MailGroup, and several new attributes have
been defined to handle email groups/mailing lists. To use this, you
will need to add this to your local
.BR oidtable.oc :
.LP
.nf
# object class for representing rfc 822 mailgroups
rfc822MailGroup: umichObjectClass.2 : \\
top : \\
cn : \\
rfc822Mailbox, member, memberOfGroup, owner, \\
errorsTo, rfc822ErrorsTo, requestsTo, rfc822RequestsTo, \\
joinable, associatedDomain, \\
description, multiLineDescription, \\
userPassword, krbName, \\
telecommunicationAttributeSet, postalAttributeSet
.fi
.LP
And you will need to add these to your local oidtable.at:
.LP
.nf
# attrs for rfc822mailgroups
multiLineDescription: umichAttributeType.2 : CaseIgnoreList
rfc822ErrorsTo: umichAttributeType.26 : CaseIgnoreIA5String
rfc822RequestsTo: umichAttributeType.27 : CaseIgnoreIA5String
joinable: umichAttributeType.28 : Boolean
memberOfGroup: umichAttributeType.29 : DN
errorsTo: umichAttributeType.30 : DN
requestsTo: umichAttributeType.31 : DN
.fi
.LP
The idea was to define a kind of hybrid mail group that could handle
people who were in X.500 or not. So, for example, members of a group
can be specified via the member attribute (for X.500 members) or the
rfc822MailBox attribute (for non-X.500 members). Similarly for the
errorsTo and rfc822ErrorsTo, and the requestsTo and rfc822RequestsTo
attributes.
.LP
To create a real mailing list, with a list maintainer, all you have to
do is create an rfc822MailGroup and fill in the errorsTo or
rfc822ErrorsTo attributes (or both). That will cause any errors
encountered when delivering mail to the group to go to the addresses
listed (or X.500 entry via it's mail attribute).
.LP
If you fill in the requestsTo or rfc822RequestsTo (or both) attributes,
mail sent to groupname-request will be sent to the addresses listed
there. If you fill in the owner attribute, mail sent to
groupname-owner will be sent to the addresses listed there. mail500
does this automatically, so you don't have to explicitly add the
groupname-request or groupname-owner aliases to your group.
.LP
To allow users to join a group, there is the joinable flag. If TRUE,
mail500 will search for entries that have a memberOfGroup attribute
equal to the DN of the group, using the same algorithm it used to find
the group in the first place (i.e. the DNs and filters listed in the
base array). This allows people to join (or subscribe to) a group
without having to modify the group entry directly. If joinable is
FALSE, the search is not done.
.SH SENDMAIL CONFIGURATION
The idea is that you might have a rule like this in your sendmail.cf
file somewhere in rule set 0:
.LP
.nf
R$*<@umich.edu>$* $#mail500$@umich.edu$:<$1>
R$*<@fax.umich.edu>$* $#fax500$@fax.umich.edu$:<$1>
.fi
.LP
These rules say that any address that ends in @umich.edu will cause
the mail500 mailer to be called to deliver the mail, and any address
that ends in @fax.umich.edu will cause the fax500 mailer to
be called. You probably
also want to do something to prevent addresses like terminator!tim@umich.edu
or tim%terminator.rs.itd.umich.edu@umich.edu from being passed to mail500.
At U-M, we do this by adding rules like this to rule set 9 where we
strip off our local names:
.LP
.nf
R<@umich.edu>$*:$* $>10<@>$1:$2
R$+%$+<@umich.edu> $>10$1%$2<@>
R$+!$+<@umich.edu> $>10$1!$2<@>
.fi
.LP
Of course, you would substitute your domain name for umich.edu in the
above examples. See the sample sendmail.cf file in the ldap source
directory clients/mail500/ for more details.
.LP
The mail500 and fax500 mailers should be defined similar to this in the
sendmail.cf file:
.LP
.nf
Mmail500, P=LIBEXECDIR/mail500, F=DFMSmnXuh, A=mail500 -f $f -h $h -m $n@$w $u
Mfax500, P=LIBEXECDIR/fax500, F=DFMSmnXuh, A=fax500 -f $f -h $h -m $n@$w $u
.fi
.LP
This defines how mail500/fax500 will be treated by sendmail and what
arguments it will have when it's called. The various flags specified
by the F=... parameter are explained in your local sendmail book (with
any luck). The arguments to mail500/fax500 are as defined under OPTIONS
above. The final argument $u is used to stand for the addresses to which
to deliver the mail.
.SH NOTES
The default values for several #defines that control how mail500
and fax500 works are configured at compile time in the
include/ldapconfig.h.edit include file. You should edit this
file to suit your site.
.SH BUGS
mail500/fax500 should use the ldap_getfilter(3) facility, instead of
compiling in the search filters to use. This is shameful.
.LP
The support for joinable groups (searching to find members who have
set something in their own entry) is really a hack because we did not
have good enough access control to allow people to add and delete
themselves from the group itself.
.LP
At one point, mail500 and fax500 were exactly the same binary, and
would behave appropriately based on how they were invoked. Unfortunately,
several new features (e.g. vacation support) were added to mail500
but not to fax500.
.SH "SEE ALSO"
.BR ldap (3),
.BR sendmail.cf (5),
.BR sendmail (8)
.SH ACKNOWLEDGEMENTS
.B OpenLDAP
is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
.B OpenLDAP
is derived from University of Michigan LDAP 3.3 Release.

View File

@ -1 +0,0 @@
fax500.8

View File

@ -473,42 +473,6 @@ typedef struct ldapmod {
#define mod_bvalues mod_vals.modv_bvals
} LDAPMod;
/*
* structures for ldap getfilter routines
*/
typedef struct ldap_filt_info {
char *lfi_filter;
char *lfi_desc;
int lfi_scope;
int lfi_isexact;
struct ldap_filt_info *lfi_next;
} LDAPFiltInfo;
typedef struct ldap_filt_list {
char *lfl_tag;
char *lfl_pattern;
char *lfl_delims;
LDAPFiltInfo *lfl_ilist;
struct ldap_filt_list *lfl_next;
} LDAPFiltList;
#define LDAP_FILT_MAXSIZ 1024
typedef struct ldap_filt_desc {
LDAPFiltList *lfd_filtlist;
LDAPFiltInfo *lfd_curfip;
LDAPFiltInfo lfd_retfi;
char lfd_filter[ LDAP_FILT_MAXSIZ ];
char *lfd_curval;
char *lfd_curvalcopy;
char **lfd_curvalwords;
char *lfd_filtprefix;
char *lfd_filtsuffix;
} LDAPFiltDesc;
/*
* structure representing an ldap session which can
* encompass connections to multiple servers (in the
@ -1463,23 +1427,8 @@ ldap_unbind_ext_s LDAP_P((
LDAPControl **clientctrls));
/*
* in getfilter.c
* (deprecated)
* in filter.c
*/
LDAP_F( LDAPFiltDesc * )
ldap_init_getfilter LDAP_P(( /* deprecated */
LDAP_CONST char *fname ));
LDAP_F( LDAPFiltInfo * )
ldap_getfirstfilter LDAP_P(( /* deprecated */
LDAPFiltDesc *lfdp,
/* LDAP_CONST */ char *tagpat,
/* LDAP_CONST */ char *value ));
LDAP_F( LDAPFiltInfo * )
ldap_getnextfilter LDAP_P(( /* deprecated */
LDAPFiltDesc *lfdp ));
LDAP_F( int )
ldap_put_vrFilter LDAP_P((
BerElement *ber,
@ -1515,10 +1464,6 @@ LDAP_F( char * )
ldap_strdup LDAP_P((
LDAP_CONST char * ));
LDAP_F( void )
ldap_getfilter_free LDAP_P((
LDAPFiltDesc *lfdp ));
LDAP_F( void )
ldap_mods_free LDAP_P((
LDAPMod **mods,

View File

@ -11,8 +11,8 @@ PROGRAMS = apitest dntest ftest ltest
SRCS = bind.c open.c result.c error.c compare.c search.c \
controls.c messages.c references.c extended.c cyrus.c \
modify.c add.c modrdn.c delete.c abandon.c cache.c \
getfilter.c sasl.c sbind.c kbind.c unbind.c \
filter.c free.c dsparse.c sort.c \
sasl.c sbind.c kbind.c unbind.c \
filter.c free.c sort.c \
getdn.c getentry.c getattr.c getvalues.c addentry.c \
request.c os-ip.c url.c sortctrl.c vlvctrl.c \
init.c options.c print.c string.c util-int.c schema.c \
@ -20,8 +20,8 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
controls.lo messages.lo references.lo extended.lo cyrus.lo \
modify.lo add.lo modrdn.lo delete.lo abandon.lo cache.lo \
getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo \
filter.lo free.lo dsparse.lo sort.lo \
sasl.lo sbind.lo kbind.lo unbind.lo \
filter.lo free.lo sort.lo \
getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \
init.lo options.lo print.lo string.lo util-int.lo schema.lo \
@ -46,7 +46,7 @@ ftest: $(XLIBS) ftest.o
ltest: $(XLIBS) test.o
$(LTLINK) -o $@ test.o $(LIBS)
CFFILES=ldap.conf ldapfilter.conf
CFFILES=ldap.conf
install-local: $(CFFILES) FORCE
-$(MKDIR) $(DESTDIR)$(libdir)

View File

@ -1,195 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/* Portions
* 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.
*
* dsparse.c: parsing routines used by display template and search
* preference file library routines for LDAP clients.
*
* 7 March 1994 by Mark C Smith
*/
#include "portable.h"
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/string.h>
#include <ac/time.h>
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include "ldap-int.h"
static int next_line LDAP_P(( char **bufp, ber_len_t *blenp, char **linep ));
static char *next_token LDAP_P(( char ** sp ));
int
ldap_int_next_line_tokens( char **bufp, ber_len_t *blenp, char ***toksp )
{
char *p, *line, *token, **toks;
int rc, tokcnt;
*toksp = NULL;
if (( rc = next_line( bufp, blenp, &line )) <= 0 ) {
return( rc );
}
if (( toks = (char **)LDAP_CALLOC( 1, sizeof( char * ))) == NULL ) {
LBER_FREE( line );
return( -1 );
}
tokcnt = 0;
p = line;
while (( token = next_token( &p )) != NULL ) {
if (( toks = (char **)LDAP_REALLOC( toks, ( tokcnt + 2 ) *
sizeof( char * ))) == NULL ) {
LBER_FREE( (char *)toks );
LBER_FREE( line );
return( -1 );
}
toks[ tokcnt ] = token;
toks[ ++tokcnt ] = NULL;
}
if ( tokcnt == 1 && strcasecmp( toks[ 0 ], "END" ) == 0 ) {
tokcnt = 0;
LDAP_VFREE( toks );
toks = NULL;
}
LBER_FREE( line );
if ( tokcnt == 0 ) {
if ( toks != NULL ) {
LBER_FREE( (char *)toks );
}
} else {
*toksp = toks;
}
return( tokcnt );
}
static int
next_line( char **bufp, ber_len_t *blenp, char **linep )
{
char *linestart, *line, *p;
ber_slen_t plen;
linestart = *bufp;
p = *bufp;
plen = *blenp;
do {
for ( linestart = p; plen > 0; ++p, --plen ) {
if ( *p == '\r' ) {
if ( plen > 1 && *(p+1) == '\n' ) {
++p;
--plen;
}
break;
}
if ( *p == '\n' ) {
if ( plen > 1 && *(p+1) == '\r' ) {
++p;
--plen;
}
break;
}
}
++p;
--plen;
} while ( plen > 0 && ( *linestart == '#' || linestart + 1 == p ));
*bufp = p;
*blenp = plen;
if ( plen <= 0 ) {
*linep = NULL;
return( 0 ); /* end of file */
}
if (( line = LDAP_MALLOC( p - linestart )) == NULL ) {
*linep = NULL;
return( -1 ); /* fatal error */
}
AC_MEMCPY( line, linestart, p - linestart );
line[ p - linestart - 1 ] = '\0';
*linep = line;
return( strlen( line ));
}
static char *
next_token( char **sp )
{
int in_quote = 0;
char *p, *tokstart, *t;
if ( **sp == '\0' ) {
return( NULL );
}
p = *sp;
while ( LDAP_SPACE( (unsigned char) *p )) { /* skip leading white space */
++p;
}
if ( *p == '\0' ) {
return( NULL );
}
if ( *p == '\"' ) {
in_quote = 1;
++p;
}
t = tokstart = p;
for ( ;; ) {
if ( *p == '\0' || ( LDAP_SPACE( (unsigned char) *p ) && !in_quote )) {
if ( *p != '\0' ) {
++p;
}
*t++ = '\0'; /* end of token */
break;
}
if ( *p == '\"' ) {
in_quote = !in_quote;
++p;
} else {
*t++ = *p++;
}
}
*sp = p;
if ( t == tokstart ) {
return( NULL );
}
return( LDAP_STRDUP( tokstart ));
}

View File

@ -60,42 +60,6 @@ ldap_strdup( LDAP_CONST char *p )
return LDAP_STRDUP( p );
}
void
ldap_getfilter_free( LDAPFiltDesc *lfdp )
{
LDAPFiltList *flp, *nextflp;
LDAPFiltInfo *fip, *nextfip;
for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = nextflp ) {
for ( fip = flp->lfl_ilist; fip != NULL; fip = nextfip ) {
nextfip = fip->lfi_next;
LDAP_FREE( fip->lfi_filter );
LDAP_FREE( fip->lfi_desc );
LDAP_FREE( fip );
}
nextflp = flp->lfl_next;
LDAP_FREE( flp->lfl_pattern );
LDAP_FREE( flp->lfl_delims );
LDAP_FREE( flp->lfl_tag );
LDAP_FREE( flp );
}
if ( lfdp->lfd_curvalcopy != NULL ) {
LDAP_FREE( lfdp->lfd_curvalcopy );
}
if ( lfdp->lfd_curvalwords != NULL ) {
LDAP_FREE( lfdp->lfd_curvalwords );
}
if ( lfdp->lfd_filtprefix != NULL ) {
LDAP_FREE( lfdp->lfd_filtprefix );
}
if ( lfdp->lfd_filtsuffix != NULL ) {
LDAP_FREE( lfdp->lfd_filtsuffix );
}
LDAP_FREE( lfdp );
}
/*
* free a null-terminated array of pointers to mod structures. the
* structures are freed, not the array itself, unless the freemods

View File

@ -1,440 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/* Portions
* Copyright (c) 1993 Regents of the University of Michigan.
* All rights reserved.
*
* getfilter.c -- optional add-on to libldap
*/
#include "portable.h"
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/errno.h>
#include <ac/regex.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ac/unistd.h>
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include "ldap-int.h"
static int break_into_words LDAP_P((
/* LDAP_CONST */ char *str,
LDAP_CONST char *delims,
char ***wordsp ));
#define FILT_MAX_LINE_LEN 1024
static LDAPFiltDesc *
ldap_init_getfilter_buf( char *buf, ber_len_t buflen )
{
LDAPFiltDesc *lfdp;
LDAPFiltList *flp, *nextflp;
LDAPFiltInfo *fip, *nextfip;
char *tag, **tok;
int tokcnt, i;
int rc;
regex_t re;
if (( lfdp = (LDAPFiltDesc *)LDAP_CALLOC( 1, sizeof( LDAPFiltDesc))) == NULL ) {
return( NULL );
}
flp = nextflp = NULL;
fip = NULL;
tag = NULL;
while ( buflen > 0 && ( tokcnt = ldap_int_next_line_tokens( &buf, &buflen, &tok ))
> 0 ) {
switch( tokcnt ) {
case 1: /* tag line */
if ( tag != NULL ) {
LDAP_FREE( tag );
}
tag = tok[ 0 ];
LDAP_FREE( tok );
break;
case 4:
case 5: /* start of filter info. list */
if (( nextflp = (LDAPFiltList *)LDAP_CALLOC( 1, sizeof( LDAPFiltList )))
== NULL ) {
ldap_getfilter_free( lfdp );
return( NULL );
}
nextflp->lfl_tag = LDAP_STRDUP( tag );
nextflp->lfl_pattern = tok[ 0 ];
if ( (rc = regcomp( &re, nextflp->lfl_pattern, 0 )) != 0 ) {
char error[512];
regerror(rc, &re, error, sizeof(error));
ldap_getfilter_free( lfdp );
#ifdef NEW_LOGGING
LDAP_LOG ( FILTER, ERR,
"ldap_init_get_filter_buf: bad regular expression %s, %s\n",
nextflp->lfl_pattern, error, 0 );
#else
Debug( LDAP_DEBUG_ANY, "ldap_init_get_filter_buf: "
"bad regular expression %s, %s\n",
nextflp->lfl_pattern, error, 0 );
#endif
errno = EINVAL;
LDAP_VFREE( tok );
return( NULL );
}
regfree(&re);
nextflp->lfl_delims = tok[ 1 ];
nextflp->lfl_ilist = NULL;
nextflp->lfl_next = NULL;
if ( flp == NULL ) { /* first one */
lfdp->lfd_filtlist = nextflp;
} else {
flp->lfl_next = nextflp;
}
flp = nextflp;
fip = NULL;
for ( i = 2; i < 5; ++i ) {
tok[ i - 2 ] = tok[ i ];
}
/* fall through */
case 2:
case 3: /* filter, desc, and optional search scope */
if ( nextflp != NULL ) { /* add to info list */
if (( nextfip = (LDAPFiltInfo *)LDAP_CALLOC( 1,
sizeof( LDAPFiltInfo ))) == NULL ) {
ldap_getfilter_free( lfdp );
LDAP_VFREE( tok );
return( NULL );
}
if ( fip == NULL ) { /* first one */
nextflp->lfl_ilist = nextfip;
} else {
fip->lfi_next = nextfip;
}
fip = nextfip;
nextfip->lfi_next = NULL;
nextfip->lfi_filter = tok[ 0 ];
nextfip->lfi_desc = tok[ 1 ];
if ( tok[ 2 ] != NULL ) {
if ( strcasecmp( tok[ 2 ], "subtree" ) == 0 ) {
nextfip->lfi_scope = LDAP_SCOPE_SUBTREE;
} else if ( strcasecmp( tok[ 2 ], "onelevel" ) == 0 ) {
nextfip->lfi_scope = LDAP_SCOPE_ONELEVEL;
} else if ( strcasecmp( tok[ 2 ], "base" ) == 0 ) {
nextfip->lfi_scope = LDAP_SCOPE_BASE;
} else {
LDAP_VFREE( tok );
ldap_getfilter_free( lfdp );
errno = EINVAL;
return( NULL );
}
LDAP_FREE( tok[ 2 ] );
tok[ 2 ] = NULL;
} else {
nextfip->lfi_scope = LDAP_SCOPE_SUBTREE; /* default */
}
nextfip->lfi_isexact = ( strchr( tok[ 0 ], '*' ) == NULL &&
strchr( tok[ 0 ], '~' ) == NULL );
LDAP_FREE( tok );
}
break;
default:
LDAP_VFREE( tok );
ldap_getfilter_free( lfdp );
errno = EINVAL;
return( NULL );
}
}
if ( tag != NULL ) {
LDAP_FREE( tag );
}
return( lfdp );
}
LDAPFiltDesc *
ldap_init_getfilter( LDAP_CONST char *fname )
{
FILE *fp;
char *buf;
long rlen, len;
int eof;
LDAPFiltDesc *lfdp;
if (( fp = fopen( fname, "r" )) == NULL ) {
return( NULL );
}
if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
fclose( fp );
return( NULL );
}
len = ftell( fp );
if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
fclose( fp );
return( NULL );
}
if (( buf = LDAP_MALLOC( (size_t)len )) == NULL ) {
fclose( fp );
return( NULL );
}
rlen = fread( buf, 1, (size_t)len, fp );
eof = feof( fp );
fclose( fp );
if ( rlen != len && !eof ) { /* error: didn't get the whole file */
LDAP_FREE( buf );
return( NULL );
}
lfdp = ldap_init_getfilter_buf( buf, rlen );
LDAP_FREE( buf );
return( lfdp );
}
LDAPFiltInfo *
ldap_getfirstfilter(
LDAPFiltDesc *lfdp,
/* LDAP_CONST */ char *tagpat,
/* LDAP_CONST */ char *value )
{
LDAPFiltList *flp;
int rc;
regex_t re;
if ( lfdp->lfd_curvalcopy != NULL ) {
LDAP_FREE( lfdp->lfd_curvalcopy );
LDAP_FREE( lfdp->lfd_curvalwords );
}
lfdp->lfd_curval = value;
lfdp->lfd_curfip = NULL;
for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
/* compile tagpat, continue if we fail */
if (regcomp(&re, tagpat, REG_EXTENDED|REG_NOSUB) != 0)
continue;
/* match tagpattern and tag, continue if we fail */
rc = regexec(&re, flp->lfl_tag, 0, NULL, 0);
regfree(&re);
if (rc != 0)
continue;
/* compile flp->ifl_pattern, continue if we fail */
if (regcomp(&re, flp->lfl_pattern, REG_EXTENDED|REG_NOSUB) != 0)
continue;
/* match ifl_pattern and lfd_curval, continue if we fail */
rc = regexec(&re, lfdp->lfd_curval, 0, NULL, 0);
regfree(&re);
if (rc != 0)
continue;
/* we successfully compiled both patterns and matched both values */
lfdp->lfd_curfip = flp->lfl_ilist;
break;
}
if ( lfdp->lfd_curfip == NULL ) {
return( NULL );
}
if (( lfdp->lfd_curvalcopy = LDAP_STRDUP( value )) == NULL ) {
return( NULL );
}
if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims,
&lfdp->lfd_curvalwords ) < 0 ) {
LDAP_FREE( lfdp->lfd_curvalcopy );
lfdp->lfd_curvalcopy = NULL;
return( NULL );
}
return( ldap_getnextfilter( lfdp ));
}
static void
ldap_build_filter(
char *filtbuf,
ber_len_t buflen,
LDAP_CONST char *pattern,
LDAP_CONST char *prefix,
LDAP_CONST char *suffix,
LDAP_CONST char *attr,
LDAP_CONST char *value,
char **valwords );
LDAPFiltInfo *
ldap_getnextfilter( LDAPFiltDesc *lfdp )
{
LDAPFiltInfo *fip;
fip = lfdp->lfd_curfip;
if ( fip == NULL ) {
return( NULL );
}
lfdp->lfd_curfip = fip->lfi_next;
ldap_build_filter( lfdp->lfd_filter, LDAP_FILT_MAXSIZ, fip->lfi_filter,
lfdp->lfd_filtprefix, lfdp->lfd_filtsuffix, NULL,
lfdp->lfd_curval, lfdp->lfd_curvalwords );
lfdp->lfd_retfi.lfi_filter = lfdp->lfd_filter;
lfdp->lfd_retfi.lfi_desc = fip->lfi_desc;
lfdp->lfd_retfi.lfi_scope = fip->lfi_scope;
lfdp->lfd_retfi.lfi_isexact = fip->lfi_isexact;
return( &lfdp->lfd_retfi );
}
static void
ldap_build_filter(
char *filtbuf,
ber_len_t buflen,
LDAP_CONST char *pattern,
LDAP_CONST char *prefix,
LDAP_CONST char *suffix,
LDAP_CONST char *attr,
LDAP_CONST char *value,
char **valwords )
{
const char *p;
char *f;
size_t slen;
int i, wordcount, wordnum, endwordnum;
if ( valwords == NULL ) {
wordcount = 0;
} else {
for ( wordcount = 0; valwords[ wordcount ] != NULL; ++wordcount ) {
;
}
}
f = filtbuf;
if ( prefix != NULL ) {
strcpy( f, prefix );
f += strlen( prefix );
}
for ( p = pattern; *p != '\0'; ++p ) {
if ( *p == '%' ) {
++p;
if ( *p == 'v' ) {
if ( LDAP_DIGIT( (unsigned char) p[1] )) {
++p;
wordnum = *p - '1';
if ( *(p+1) == '-' ) {
++p;
if ( LDAP_DIGIT( (unsigned char) p[1] )) {
++p;
endwordnum = *p - '1'; /* e.g., "%v2-4" */
if ( endwordnum > wordcount - 1 ) {
endwordnum = wordcount - 1;
}
} else {
endwordnum = wordcount - 1; /* e.g., "%v2-" */
}
} else {
endwordnum = wordnum; /* e.g., "%v2" */
}
if ( wordcount > 0 ) {
for ( i = wordnum; i <= endwordnum; ++i ) {
if ( i > wordnum ) { /* add blank btw words */
*f++ = ' ';
}
slen = strlen( valwords[ i ] );
AC_MEMCPY( f, valwords[ i ], slen );
f += slen;
}
}
} else if ( *(p+1) == '$' ) {
++p;
if ( wordcount > 0 ) {
wordnum = wordcount - 1;
slen = strlen( valwords[ wordnum ] );
AC_MEMCPY( f, valwords[ wordnum ], slen );
f += slen;
}
} else if ( value != NULL ) {
slen = strlen( value );
AC_MEMCPY( f, value, slen );
f += slen;
}
} else if ( *p == 'a' && attr != NULL ) {
slen = strlen( attr );
AC_MEMCPY( f, attr, slen );
f += slen;
} else {
*f++ = *p;
}
} else {
*f++ = *p;
}
if ( (size_t) (f - filtbuf) > buflen ) {
/* sanity check */
--f;
break;
}
}
if ( suffix != NULL && ( (size_t) (f - filtbuf) < buflen ) )
{
strcpy( f, suffix );
} else {
*f = '\0';
}
}
static int
break_into_words( /* LDAP_CONST */ char *str, LDAP_CONST char *delims, char ***wordsp )
{
char *word, **words;
int count;
char *tok_r;
if (( words = (char **)LDAP_CALLOC( 1, sizeof( char * ))) == NULL ) {
return( -1 );
}
count = 0;
words[ count ] = NULL;
word = ldap_pvt_strtok( str, delims, &tok_r );
while ( word != NULL ) {
if (( words = (char **)LDAP_REALLOC( words,
( count + 2 ) * sizeof( char * ))) == NULL ) {
return( -1 );
}
words[ count ] = word;
words[ ++count ] = NULL;
word = ldap_pvt_strtok( NULL, delims, &tok_r );
}
*wordsp = words;
return( count );
}

View File

@ -1,109 +0,0 @@
# $OpenLDAP$
#
# ldap filter file
#
# lines like this that start with # or empty lines are ignored
#
# syntax:
#
# <tag>
# <pattern1> <delimiters> <filter1-1> <desc1-1> [<scope>]
# <filter1-2> <desc1-2> [<scope>]
#
# <pattern2> <delimiters> <filter2-1> <desc2-1> [<scope>] ...
#
# The "desc" should describe the filter and it should correctly complete
# both of the following phrases:
#
# One <desc> match was found for...
# Three <desc> matches were found for...
#
# The scope is optional, and should be one of:
# "base"
# "onelevel"
# "subtree"
# if it is included.
#
"finger and ud and go500 and go500gw subtree and web500gw subtree and rp500 and rcpt500 and ufn last"
"^$" "" "(objectclass=*)" "default filter"
"=" " " "%v" "arbitrary filter"
"^[0-9][0-9\-]*$" " " "(telephoneNumber=*%v)" "phone number"
"@" " " "(mail=%v)" "email address"
"(mail=%v*)" "start of email address"
"^.[\. _].*" ". _" "(cn=%v1* %v2-)" "first initial"
".*[. _].$" ". _" "(cn=%v1-*)" "last initial"
"[. _]" ". _" "(|(sn=%v1-)(cn=%v1-))" "exact"
"(|(sn~=%v1-)(cn~=%v1-))" "approximate"
".*" ". " "(|(cn=%v1)(sn=%v1)(ou=%v1))" "exact"
"(|(cn~=%v1)(sn~=%v1)(ou~=%v1))" "approximate"
"go500gw onelevel and web500gw onelevel and ufn first and ufn intermediate"
"^$" "" "(!(objectclass=dSA))" "default filter"
"=" " " "%v" "arbitrary filter"
"^..$" " " "(|(o=%v)(c=%v)(l=%v)(co=%v))" "exact2"
"(|(o~=%v)(c~=%v)(l~=%v)(co~=%v))" "approximate2"
" " " " "(|(o=%v)(l=%v)(co=%v)(ou=%v))" "exact"
"(|(o~=%v)(l~=%v)(co~=%v)(ou~=%v))" "approximate"
"\." " " "(associatedDomain=%v)" "exact"
".*" " " "(|(o=%v)(l=%v)(co=%v)(ou=%v))" "exact"
"(|(o~=%v)(l~=%v)(co~=%v)(ou~=%v))" "approximate"
#
# xax500
#
"xax500"
"=" " " "(%v)" "arbitrary filter"
"^[0-9][0-9-]*$" " " "(telephoneNumber=*%v)" "phone number"
"@" " " "(mail=%v)" "email address"
"(mail=%v*)" "start of email address"
"^.[. _].*" ". _" "(cn=%v1* %v2-)" "first initial"
".*[. _].$" ". _" "(cn=%v1-*)" "last initial"
"[. _]" ". _" "(|(sn=%v1-)(cn=%v1-))" "exact"
"(|(sn~=%v1-)(cn~=%v1-))" "approximate"
".*" ". " "(|(cn=%v1)(sn=%v1)(uid=%v1))" "exact"
"(|(cn=%v1)(sn~=%v1))" "approximate"
"xax500-auth"
"=" " " "(%v)" "arbitrary filter"
"^[0-9][0-9-]*$" " " "(telephoneNumber=*%v)" "phone number"
"@" " " "(mail=%v)" "email address"
"(mail=%v*)" "start of email address"
"^.[. _].*" ". _" "(cn=%v1* %v2-)" "first initial"
".*[. _].$" ". _" "(cn=%v1-*)" "last initial"
"[. _]" ". _" "(|(sn=%v1-)(cn=%v1-))" "exact"
"(|(sn~=%v1-)(cn~=%v1-))" "approximate"
".*" ". " "(|(cn=%v1)(sn=%v1)(uid=%v1))" "exact"
"(|(cn=%v1)(sn~=%v1))" "approximate"
"list500"
"[. _]" ". _" "(|(sn=%v1-)(cn=%v1-))" "exact"
"(|(sn~=%v1-)(cn~=%v1-))" "approximate"
".*" ". " "(|(cn=%v1)(sn=%v1)(uid=%v1))" "exact"
"(|(cn~=%v1)(sn~=%v1))" "approximate"

View File

@ -171,10 +171,6 @@ SOURCE=.\dnssrv.c
# End Source File
# Begin Source File
SOURCE=.\dsparse.c
# End Source File
# Begin Source File
SOURCE=.\error.c
# End Source File
# Begin Source File
@ -203,10 +199,6 @@ SOURCE=.\getentry.c
# End Source File
# Begin Source File
SOURCE=.\getfilter.c
# End Source File
# Begin Source File
SOURCE=.\getvalues.c
# End Source File
# Begin Source File

View File

@ -13,8 +13,8 @@ XXSRCS = apitest.c test.c \
bind.c open.c result.c error.c compare.c search.c \
controls.c messages.c references.c extended.c cyrus.c \
modify.c add.c modrdn.c delete.c abandon.c cache.c \
getfilter.c sasl.c sbind.c kbind.c unbind.c \
filter.c free.c dsparse.c sort.c \
sasl.c sbind.c kbind.c unbind.c \
filter.c free.c sort.c \
getdn.c getentry.c getattr.c getvalues.c addentry.c \
request.c os-ip.c url.c sortctrl.c vlvctrl.c \
init.c options.c print.c string.c util-int.c schema.c \
@ -28,8 +28,8 @@ OBJS = threads.lo rdwr.lo tpool.lo \
bind.lo open.lo result.lo error.lo compare.lo search.lo \
controls.lo messages.lo references.lo extended.lo cyrus.lo \
modify.lo add.lo modrdn.lo delete.lo abandon.lo cache.lo \
getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo \
filter.lo free.lo dsparse.lo sort.lo \
sasl.lo sbind.lo kbind.lo unbind.lo \
filter.lo free.lo sort.lo \
getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \
init.lo options.lo print.lo string.lo util-int.lo schema.lo \

View File

@ -632,7 +632,7 @@ rewrite_xmap_apply(
case REWRITE_MAP_XLDAPMAP: {
LDAP *ld;
char filter[ LDAP_FILT_MAXSIZ ];
char filter[1024];
LDAPMessage *res = NULL, *entry;
LDAPURLDesc *lud = ( LDAPURLDesc * )map->lm_args;
int attrsonly = 0;