\documentclass{ictlab}
%\documentclass[solutions]{ictlab}
\RCS $Revision: 1.18 $
\usepackage{verbatim,key,alltt,amstext,answer2,biganswerbox}
\usepackage[hang,bf,nooneline]{caption2}
\usepackage[pdfpagemode=None,pdfauthor={Nick Urbanik}]{hyperref}
\newcommand*{\labTitle}{LDAP Filters and Searching LDAP Directories}
%% \providecommand*{\SNMP}{\acro{SNMP}\xspace}
%% \providecommand*{\MIB}{\acro{MIB}\xspace}
%% \providecommand*{\ID}{\acro{ID}\xspace}
%% \providecommand*{\OID}{\acro{OID}\xspace}
%% \providecommand*{\FAQ}{\acro{FAQ}\xspace}
%% \providecommand*{\RPM}{\acro{RPM}\xspace}
%% \providecommand*{\MRTG}{\acro{MRTG}\xspace}
%% \providecommand*{\CPAN}{\acro{CPAN}\xspace}
%% \providecommand*{\RRD}{\acro{RRD}\xspace}
%% \providecommand*{\URL}{\acro{URL}\xspace}
%% \providecommand*{\DN}{\acro{DN}\xspace}
%% \providecommand*{\LDIF}{\acro{LDIF}\xspace}
\providecommand*{\IETF}{\acro{IETF}\xspace}
\providecommand*{\SQL}{\acro{SQL}\xspace}
\renewcommand*{\floatpagefraction}{0.75} % default is .5, to increase
% density.
\renewcommand*{\bottomfraction}{0.6} % default is 0.3
\renewcommand*{\topfraction}{0.85} % default is 0.7
\renewcommand*{\textfraction}{0.1} % default is 0.2
\begin{document}
\section{Background:}
A \emph{grammar} is a notation that defines the \emph{syntax} of a
computer language. You have already seen an example of a grammar on
slides 22 and 23 of \texttt{Lecture8} (about Interaction Diagrams) in
your \acro{OOT} notes, defining the rules for the message label syntax
of collaboration diagrams.\footnote{Please stop telling me you have
never seen a grammar before!}
Today we look at the syntax of \LDAP \emph{filters}, a simple
\emph{standard} language used in defining searches of an \LDAP
directory. It corresponds loosely to the \SQL \texttt{SELECT}
statement, except that it is very stardardised. We start by looking
at a grammar that defines the syntax of \LDAP filters.
\subsection{A Grammar that Defines the Syntax of LDAP Filters}
\label{sec:grammar}
The rules for the grammar are given in \RFC 822. You can find this
\RFC (and the others) at \url{http://www.faqs.org/rfcs/rfc822.html}.
Let me summarise the description of the grammar from the \RFC for
you.
\begin{itemize}
\item a \emph{rule} is given by a name such as \texttt{filter},
\texttt{filtercomp},\ldots\ \ Eventually a rule is further defined
until it consists of \texttt{literal values}, and values such as
\texttt{AttributeDescription} or \texttt{AttributeValue}, both
defined in \RFC 2251.
\item a \emph{literal value} is put in double quotes, such as
\texttt{"("}, \texttt{")"},
\texttt{"="}, \texttt{">="}, \texttt{"*"}\ldots{} below. A literal
value is simply typed into the filter just the way it is written;
from this, we see that every \texttt{filter} is always enclosed in
parentheses (see the examples in section~\vref{sec:examples}).
\item \emph{alternatives} are separated by a slash \texttt{"/"}. For
example, the rule:
\begin{verbatim}
item = simple / present / substring / extensible
\end{verbatim}
means that an \texttt{item} is either defined by the rule for
\texttt{simple}, or for \texttt{present}, or for \texttt{substring},
or for the rule defining \texttt{extensible}.
\item An \emph{optional} item is in square brackets, such as in the
rule
\begin{verbatim}
substring = attr "=" [initial] any [final]
\end{verbatim}
where \texttt{initial} and \texttt{final} are optional.
\item \emph{grouping} is defined by enclosing the elements in
parentheses, so that they are treated as a single element. So
``\texttt{elem (foo / bar) elem)}'' can match ``\texttt{elem foo
elem}'' and ``\texttt{elem bar elem}.'' See the
definition of the rule \texttt{any} below for another example.
\item \emph{repetition} is defined with a ``\texttt{*}'' appearing
before a rule. For example,
\begin{verbatim}
*filter
\end{verbatim}
means ``zero or more repetitions of a \texttt{filter}.'' A number in
front of the star is a minimum number of repetitions, so
\begin{verbatim}
1*filter
\end{verbatim}
means ``one or more repetitions of \texttt{filter}.''
Let us look at the definition of \texttt{any}:
\begin{verbatim}
any = "*" *(value "*")
\end{verbatim}
This means that to type in part of an \LDAP filter that is defined by
\texttt{any}, we type:
\begin{itemize}
\item a literal star, i.e., \texttt{*} (in other words, we type
\key{Shift-8})
\item Next we type zero or more repetitions of:
\begin{itemize}
\item a legal attribute value, followed immediately by
\item a star \texttt{*} (in other words, we type
\key{Shift-8})
\end{itemize}
\end{itemize}
The following lines contain text that matches this definition of
\texttt{any}:
\begin{verbatim}
*
*1*
*this*
*this*that*
*1*2*3*4*5*6*7*8*9*10*11*12*13*14*
\end{verbatim}
\end{itemize}
Note that an \texttt{AttributeValue} cannot be empty, or contain an
unquoted star \texttt{*}.
An important thing to understand is that a grammar only defines the
\emph{syntax}, not the meaning of a computer language.
Now let us look at the complete grammar itself.
From \texttt{/usr/share/doc/openldap-2.0.27/rfc/rfc2254.txt};
\begin{alltt}
filter = "(" filtercomp ")"
filtercomp = and / or / not / item
and = "&" filterlist
or = "|" filterlist
not = "!" filter
filterlist = 1*filter
item = simple / present / substring / extensible
simple = attr filtertype value
filtertype = equal / approx / greater / less
equal = "="
approx = "~="
greater = ">="
less = "<="
extensible = attr [":dn"] [":" matchingrule] ":=" value
/ [":dn"] ":" matchingrule ":=" value
present = attr "=*"
substring = attr "=" [initial] any [final]
initial = value
any = "*" *(value "*")
final = value
attr = AttributeDescription from Section 4.1.5 of [1]
matchingrule = MatchingRuleId from Section 4.1.9 of [1]
value = AttributeValue from Section 4.1.6 of [1]
\end{alltt}%$
The reference marked ``\texttt{[1]}'' is \texttt{rfc2251}.
\subsection{Examples of LDAP Filters}
\label{sec:examples}
Here are some examples of \LDAP filters from \texttt{rfc2254.txt}:
\begin{alltt}
(cn=Babs Jensen)
(!(cn=Tim Howes))
(&(objectClass=Person)(|(sn=Jensen)(cn=Babs J*)))
(o=univ*of*mich*)
\end{alltt}
\subsection{Using \texttt{ldapsearch}}
\label{sec:ldapsearch}
Here is an example of using \texttt{ldapsearch} to search our \LDAP
server, shown in the lecture:
\begin{alltt}
ldapsearch -x '(|(acType=STF)(&(year=3)(course=41300)(classcode=W)))' cn
\end{alltt}
Here are two examples of searching the \VTC \LDAP server, from the lecture:
\begin{verbatim}
ldapsearch -x -h ldap.vtc.edu.hk -b "ou=ICT,ou=TY,o=ftstudent,dc=vtc.edu.hk" \
'(|(acType=STF)(&(year=3)(course=41300)(classcode=W)))' uid
\end{verbatim}
and
\begin{verbatim}
ldapsearch -x -h ldap.vtc.edu.hk -b "ou=ICT,ou=TY,o=staff,dc=vtc.edu.hk" \
'(|(acType=STF)(&(year=3)(course=41300)(classcode=W)))' cn
\end{verbatim}
Some points about \texttt{ldapsearch}:
\begin{enumerate}
\item You need to use simple authentication with our server. It will
not work unless you use the option ``\texttt{-x}''.
\item The default host and base for the \LDAP server are set in the
file \texttt{/etc\allowbreak/openldap\allowbreak/ldap.conf}. They
will be set to
\begin{verbatim}
BASE dc=tyict,dc=vtc,dc=edu,dc=hk
HOST ldap.tyict.vtc.edu.hk
\end{verbatim}
if you configured your machine correctly with \texttt{authconfig}
when you installed Linux\@.
\item To choose another \LDAP server, such as the \VTC \LDAP server,
use the ``\texttt{-h \emph{hostname}}'' option, where
\texttt{\emph{hostname}} is the hostname of the \LDAP server.
\item To choose a different base \DN, use the ``\texttt{-b
"\emph{base-distinguished-name"}}'' option. Quote the \DN,
otherwise the shell will interpret the ``\texttt{=}'' signs.
\item You can authenticate to the \LDAP server with a \emph{bind}
operation. To authenticate as yourself using \texttt{ldapsearch},
use the options \texttt{-D
'uid=\emph{your-user-id},\allowbreak{}ou=People,\allowbreak
dc=tyict,\allowbreak{}dc=vtc,\allowbreak{}dc=edu,\allowbreak{}dc=hk'
-W}
The \texttt{-W} option causes you to be prompted for your password.
You need to bind and search at the same time!
\end{enumerate}
\subsection{LDAP URLs}
\label{sec:ldap-urls}
The grammar for an \LDAP \URL is defined by \RFC 2255.
An \LDAP \URL has the form:
\begin{alltt}
ldap://\emph{host}[:\emph{port}]/\emph{base}?\emph{attr}?\emph{scope}?\emph{filter}
\end{alltt}
Here is a (partial) grammar:
\begin{alltt}
ldapurl = ldap://" [hostport] ["/"
[dn ["?" [attributes] ["?" [scope]
["?" [filter] ["?" extensions]]]]]]
\end{alltt}
Examples:
\begin{verbatim}
ldap://ictlab/ou=People,dc=tyict,dc=vtc,dc=edu,dc=hk?uid?one?(uid=nicku)
\end{verbatim}
%% Can enter this into Netscape 4.7.x to see \LDAP entry for me:
%% \begin{verbatim}
%% ldap://ictlab/ou=People,dc=tyict,dc=vtc,dc=edu,dc=hk??one?(uid=nicku)
%% \end{verbatim}
%% \subsection{Authenticating Web Applications using LDAP}
%% \label{sec:auth_ldap}
%% Both Red Hat 8 and 9 use Apache 2.0.40, which does not have the module
%% for \LDAP authentication built in.\footnote{\texttt{mod\_auth\_ldap}
%% support was added to Apache version 2.0.41. There is now an Apache
%% software package 2.0.45 in rawhide, so support for
%% \texttt{mod\_auth\_ldap} will come back in the next version of Red
%% Hat Linux.}
%% %% I have built Apache \RPM{}s that support \LDAP authentication. I have
%% %% built two sets: one set based on the latest update for Red Hat 8.0,
%% %% the other for the latest Apache update for Red Hat 9.
%% Previous versions of Red Hat Linux had the \texttt{auth\_ldap}
%% software package with Apache 1.3.x, which supports \LDAP web
%% authentication in the same way.
%% %% Install them on your computer first:
%% %% \begin{alltt}
%% %% $ \textbf{cd /home/nfs/redhat/contrib}
%% %% $ \textbf{sudo rpm -Uhv httpd-*.rpm mod_ssl-*.rpm}
%% %% Preparing... ########################################### [100%]
%% %% 1:httpd ########################################### [ 25%]
%% %% 2:httpd-devel ########################################### [ 50%]
%% %% 3:httpd-manual ########################################### [ 75%]
%% %% 4:mod_ssl ########################################### [100%]
%% %% \end{alltt}
%% Here is an example of a file \texttt{/etc/httpd/conf.d/ldap.conf}
%% for authenticating staff only, to the web location
%% \texttt{http://\allowbreak localhost/\allowbreak staff/}
%% \begin{verbatim}
%%
%% AuthType Basic
%% AuthName "LDAP authentication to staff only"
%% AuthLDAPURL ldap://ldap.tyict.vtc.edu.hk/ou=People,dc=tyict,dc=vtc,
%% dc=edu,dc=hk?uid?one?(acType=STF)
%% require valid-user
%%
%% \end{verbatim}
%% Note that the \LDAP \URL is wrapped here, but should be all on one
%% line.
%% For the manual, see
%% \url{http://httpd.apache.org/docs-2.0/mod/mod_auth_ldap.html}, and
%% also
%% \url{http://httpd.apache.org/docs-2.0/mod/mod_ldap.html}.
\subsection{About LDIF}
\label{sec:ldif}
\LDIF is the format of text data used to read and write an \LDAP
server. \LDIF has a simple format that you can see as the result of
any \LDAP search.
The name of each attribute starts a line (no spaces before the
attribute name), and is followed by a colon `\texttt{:}' and a single
space, then its value. If the value is too long to conveniently fit
on one line, it can be ``folded'' onto more than one line. After a
line break, the folded line continues with exactly one space before
the continued line.
If the entry contains leading spaces, or any other special characters
(for example if it is a photo), then it can be encoded with
\acro{BASE64} encoding. On a Linux system, you can decode such text
by running the program \texttt{mimencode -u}, and then you can copy
and paste the encoded text as input to \texttt{mimencode -u}.
\section{Procedure}
\label{sec:procedure}
\begin{enumerate}
\item Which of the following text from parts of \LDAP filters match
the definition of \texttt{any} from the grammar for \LDAP
filters?\answerbox{\textbf{c} and \textbf{f} only, since the grammar
requires a match to \texttt{any} to begin and end with an asterisk.}%
If you put the string
``\texttt{o=}'' in front of each, which ones match the definition of
\texttt{substring}?\answerbox{All of them do, except for
\textbf{(d)}, since two asterisks together do not match the
definition of \texttt{substring} in the grammar.}
\begin{enumerate}
\item \texttt{*John}
\item \texttt{John*}
\item \texttt{*John*}
\item \texttt{this*is**John*}
\item \texttt{*is*this*John*}
\item \texttt{*How*about*this*one*here*}
\end{enumerate}
\item For each of the following filters, if you remove the external
parentheses,
indicate what term in the grammar the result matches, for example,
\texttt{simple}, \texttt{present}, \texttt{substring},\ldots
\begin{enumerate}
\item \texttt{(!(cn=nicku))}\answerbox{This matches \texttt{not}}
\item \texttt{(cn=Nick*)}\answerbox{This matches \texttt{substring}}
\item \texttt{(cn=*)}\answerbox{This matches \texttt{present}}
\end{enumerate}
%% Note: the term \emph{item} is defined in the grammar for filters
%% above.
\item
\begin{enumerate}
\item Write a filter that shows the \LDAP entry for your account on
\texttt{ldap\allowbreak.tyict\allowbreak.vtc\allowbreak.edu\allowbreak.hk}.
Test it using \texttt{ldapsearch}.
\begin{biganswerbox}[0.8cm]%
\begin{solution}%
\texttt{(uid=nicku)}\\
Note that the parentheses are required by the grammar. Some
software may forgive you for leaving out the outer pair, but
some may not. When writing software using \LDAP filters,
always put the parentheses in. Here is a call using
\texttt{ldapsearch}, assuming the configuration file
\texttt{/etc/openldap/ldap.conf}
is set up correctly:
\begin{alltt}
$ \textbf{ldapsearch -x '(uid=nicku)'}
\end{alltt}%$
Why did I need to quote the filter?\\
{\tiny (Because the shell will interpret parentheses as a
request to start a subshell.)}
\end{solution}
\end{biganswerbox}
\item Now repeat the search, but \emph{bind} to your account using
the options \texttt{-D \meta{yourDN} -W}. Use \texttt{diff} to
compare the results. Is there any difference in the attributes
returned?\answerbox{%
Yes. I obtained the output in each case like this:\\
\texttt{\$ \textbf{ldapsearch -x '(uid=nicku) > $\sim$/noauth.ldif}}\\
\texttt{\$ \textbf{ldapsearch -x -D
'uid=nicku,ou=People,dc=tyict,\allowbreak{}dc=vtc,%
\allowbreak{}dc=edu,\allowbreak{}dc=hk' -W
'(uid=nicku)' > $\sim$/auth.ldif}}\\
\texttt{\$ \textbf{diff -u $\sim$/noauth.ldif $\sim$/auth.ldif}}\\
The difference was that my \acro{MD}5-hashed password was visible when
I did the search while binding to the server. } If so, explain
why.\answerbox{The server has permissions that only let a user see
their own password, which is after they have authenticated with
a \texttt{bind} operation.}
\end{enumerate}
\item Write a filter to select all students in your
class.
\begin{biganswerbox}%
\begin{solution}%
\texttt{(\&(year=3)(classCode=X))}\\
Here I am cheating a little, since I know that only students
in the \CSA course have class codes near the end of the
alphabet.\\[2ex]
If there are some classes in the directory that are also in
class X, but are not in the \CSA course, then we need to
specify the course something like this:\\
\texttt{(\&(course=41300)(year=3)(classCode=X))}
\end{solution}
\end{biganswerbox}
Test it using \texttt{ldapsearch}; display only the names of the
students.
\begin{biganswerbox}[8mm]%
\begin{solution}%
Okay, we can do this:
\begin{alltt}
$ \textbf{ldapsearch -x '(&(course=41300)(year=3)(classCode=X))' cn |
grep 'cn:' | awk -F': ' '\{print $NF\}'}
Lau Chi-sang
Ma Ka-fai
Lee Chun-kit, Dennis
Chan Chi-wai
Tam Ying-yin
Tsui Yuet-man
Wong Kai-tung
Leung Wing-yee
Sham Shu-ho
Liu Chin-keung
Chan Wing-him
Ng Chun-tung
Wong Sze-ming
Lam Chun-kit, Wendell
Cheuk Wai-hung
Chan Kwong-yiu
Cheng Kwok-wai
Kan Shu-wing
Chiu Chun-keung
Mok Chi-wing
\end{alltt}
\end{solution}
\end{biganswerbox}
\item Write a filter to select all students in year 2 of the \ICT
Department\@.\\
\answerbox[.6\columnwidth]{%
If we assume that only \ICT students are in the directory, then
this would do: \\
\texttt{(year=2)}\\[1ex]
However, this is not a safe assumption, so it is better to use the
\texttt{department} attribute:\\
\texttt{(\&(department=ICT)(year=2))}
}%
Count the number of students that is returned.\answerbox{%
\texttt{\$ \textbf{ldapsearch -x '(\&(department=ICT)(year=2))' dn \textbar\\
grep '\textasciicircum{}dn:' \textbar\ wc -l}\\
\hspace*{2em}371}
}%
\item Determine the number of entries at the one level immediately below
the base level of the \LDAP server
\texttt{ldap\allowbreak.tyict\allowbreak.vtc\allowbreak.edu\allowbreak.hk}.
In other words, all entries \emph{immediately} below the \DN
\texttt{dc=tyict, dc=vtc, dc=edu, dc=hk}.\\\answerbox{%
As Albert taught you so well last year, there are three scopes for
searching a directory:\\
%% \begin{description}
%% \item[base] where you search only the base
%% entry for attributes that match your filter,
%% \item[one level] where you search the base entry and all entries
%% immediately below the base entry,
%% \item[sub] A subtree scope results in searching the base entry and
%% all entries below it in the directory tree.
%% \end{description}
\emph{base} where you search only the base
entry for attributes that match your filter,\\
\emph{one level} where you search all entries
immediately below the base entry, but \emph{not} the base entry itself, \\
\emph{sub}: a subtree scope results in searching the base entry
and
all entries below it in the directory tree.\\
These are selected in the \texttt{ldapsearch} command with the
scope option \texttt{-s}:\\
\texttt{\$ \textbf{ldapsearch -x -s one dn \textbar\ grep
'\textasciicircum{}dn:' \textbar\ wc -l}\hfill\\[1ex]
\hspace*{2em}\texttt{17}}%
}
Determine the \DN of your entry in both servers, in our server
\texttt{ldap\allowbreak.tyict\allowbreak.vtc\allowbreak
.edu\allowbreak.hk}:\answerbox[.6\columnwidth]{%
\texttt{\$ \textbf{ldapsearch -x -LLL '(uid=nicku)' dn}\\
dn: uid=nicku,ou=People,dc=tyict,dc=vtc,dc=edu,dc=hk}\\
Here is a search for a student:\\
\texttt{\$ \textbf{ldapsearch -x -LLL '(uid=010954118)' dn}\\
dn: uid=010954118,ou=People,dc=tyict,dc=vtc,dc=edu,dc=hk
}\\
In both cases, the entry is at at two levels below the base: we have
base, then \texttt{ou=People}, then the entry for the person.
}%
and in
\texttt{ldap\allowbreak.vtc\allowbreak.edu\allowbreak
.hk}:\answerbox[.6\columnwidth]{%
\texttt{\$ \textbf{ldapsearch -x -LLL -b 'dc=vtc.edu.hk' -h
ldap.vtc.edu.hk
\bs\\
'(uid=nicku)' dn}\\
dn: uid=nicku, ou=ICT, ou=TY, o=staff, dc=vtc.edu.hk}\\
And here is a search for the same student as above:\\
\texttt{\$ \textbf{ldapsearch -x -LLL -b 'dc=vtc.edu.hk' -h
ldap.vtc.edu.hk
\bs\\
'(uid=10954118)' dn}\\
dn: uid=10954118, ou=ICT, ou=TY, ou=ftstudent, dc=vtc.edu.hk}\\
Note that in this case, my entry is four levels below the base:\\
base $\longrightarrow$ \texttt{o=staff} $\longrightarrow$
\texttt{ou=TY} $\longrightarrow$ \texttt{ou=ICT}
$\longrightarrow$ entry for \texttt{nicku}.\\
The entry for the student is also four levels below the base:\\
base $\longrightarrow$ \texttt{ou=ftstudent} $\longrightarrow$
\texttt{ou=TY} $\longrightarrow$ \texttt{ou=ICT} $\longrightarrow$
entry for student.
}%
Is the structure of the directory hierarchical or flat?\answerbox{%
Neither directory tree is totally flat, but the fact that all
entries in our directory are two levels below the base, while the
level of a user in the \VTC directory is four levels down
indicates that the \VTC directory has been designed with a more
hierarchical structure.\\[1ex]
Although it seems that this design is more beautiful and it seems
as if will be easier to manage, any reorganisation of the \VTC
will require major changes to the directory. Since a directory is
mission critical, it is better to structure the directory so that
changes in the organisation will
require less radical re-organisation of the directory structure.\\[1ex]
With the design of the \ICT directory, we can reorganise the
directory simply by changing attributes within the affected
entries, rather than changing their distinguished names, and
changing their relative distinguished names. If we want to
introduce a new category that is neither staff nor student (such
as alumni for graduates of \ICT), then we can simply introduce a
new value for an attribute.\\
The authorities who designed \LDAP, created the \IETF standards,
and wrote the code, said many times that a flatter directory
structure is better \emph{within the constraints of replicating
the directory, of organising referrals from one directory to
another, and administrative concerns.} I trust them, and
perhaps
you should too.%
}
Compare this with the \VTC \LDAP server,
\texttt{ldap\allowbreak.vtc\allowbreak.edu\allowbreak.hk}, looking
under the base \texttt{dc=vtc.edu.hk}. Is the \VTC \LDAP server
hierarchical or flat in structure?
%% \item Determine the common names of the members of the group at the \DN
%% \texttt{cn=CDSmartGuys,\allowbreak{}o=vtc.edu.hk}. Note that in \LDIF output,
%% any attribute may be folded and also \acro{BASE64} encoded. See
%% section~\vref{sec:ldif}.\\\answerbox[.6\columnwidth]{}
% ldapsearch -x -h ldap.vtc.edu.hk -b'o=vtc.edu.hk' '(|(uid=hmpoon)(uid=lkkwok)(uid=joeytang))' cn
%% $ ldapsearch -x -h ldap.vtc.edu.hk -b'o=vtc.edu.hk' '(|(uid=hmpoon)(uid=lkkwok)(uid=joeytang))' cn
%% version: 2
%% #
%% # filter: (|(uid=hmpoon)(uid=lkkwok)(uid=joeytang))
%% # requesting: cn
%% #
%% # lkkwok, ITSD, vtc.edu.hk
%% dn: uid=lkkwok, ou=ITSD, o=vtc.edu.hk
%% cn: Kwok Lung Kei [ITSD]
%% # hmpoon, ITSD, vtc.edu.hk
%% dn: uid=hmpoon, ou=ITSD, o=vtc.edu.hk
%% cn: POON HO MAN, HERMAN [ITSD]
%% # joeytang, ITSD, vtc.edu.hk
%% dn: uid=joeytang,ou=ITSD,o=vtc.edu.hk
%% cn: Tang Ka Ki, Joey [ITSD]
%$
%% \item Determine the common names of the members of the group at the \DN
%% \texttt{cn=cdurl,\allowbreak{}o=vtc.edu.hk}. Note that in \LDIF output,
%% any attribute may be folded and also \acro{BASE64} encoded. See
%% section~\vref{sec:ldif}.\\\answerbox[.6\columnwidth]{%
%% Kwok Lung Kei
%% [ITSD], POON HO MAN, HERMAN [ITSD], Tang Ka Ki, Joey [ITSD]\\
%% \texttt{\$ ldapsearch -x -LLL -h ldap.vtc.edu.hk -b 'o=vtc.edu.hk' -s
%% one \bs\\
%% '(\&(objectclass=groupofuniquenames)(cn=cdurl))'\\
%% dn: cn=cdurl,o=vtc.edu.hk\\
%% description: CD URL\\
%% cn: cdurl\\
%% mail: cdurl@vtc.edu.hk\\
%% mgmanjoinability: Closed\\
%% mgmanjoinlocaltype: MOG\\
%% mgmanmembervisibility: Closed\\
%% mgmanhidden: false\\
%% mgrpbroadcasterpolicy: NO\_REQUIREMENTS\\
%% mgrpmsgrejectaction: REPLY\\
%% objectclass: top\\
%% objectclass: groupofuniquenames\\
%% objectclass: groupofurls\\
%% objectclass: mailgroup\\
%% objectclass: mailgroupmanagement\\
%% memberurl: ldap:///o=vtc.edu.hk??sub?(\textbar (uid=hmpoon)\\
%% \mbox{}~(uid=flofung)(uid=joeytang))\\
%% mailhost: hqmail.vtc.edu.hk\\
%% mgrpallowedbroadcaster: uid=flofung,ou=ITSD,o=vtc.edu.hk\\
%% mgrpallowedbroadcaster: uid=hmpoon,ou=ITSD,o=vtc.edu.hk\\
%% mgrpallowedbroadcaster: uid=joeytang,ou=ITSD,o=vtc.edu.hk\\[2ex]
%% \$ ldapsearch -x -LLL -b 'o=vtc.edu.hk' -h ldap.vtc.edu.hk \bs\\
%% '(\textbar(uid=hmpoon)(uid=flofung)(uid=joeytang))' cn\\
%% dn: uid=flofung, ou=ITSD, o=vtc.edu.hk\\
%% cn: Florence Fung [ITSD]\\[2ex]
%% dn: uid=hmpoon, ou=ITSD, o=vtc.edu.hk\\
%% cn: POON HO MAN, HERMAN [ITSD]\\[2ex]
%% dn: uid=joeytang,ou=ITSD,o=vtc.edu.hk\\
%% cn: Tang Ka Ki, Joey [ITSD]
%% }% end of texttt
%% }
%% $ ldapsearch -x -h ldap.vtc.edu.hk -b 'o=vtc.edu.hk' -s one '(&(objectclass=groupofuniquenames)(cn=cdurl))'
%% version: 2
%% #
%% # filter: (&(objectclass=groupofuniquenames)(cn=cdurl))
%% # requesting: ALL
%% #
%% # cdurl, vtc.edu.hk
%% dn: cn=cdurl,o=vtc.edu.hk
%% description: CD URL
%% cn: cdurl
%% mail: cdurl@vtc.edu.hk
%% mgmanjoinability: Closed
%% mgmanjoinlocaltype: MOG
%% mgmanmembervisibility: Closed
%% mgmanhidden: false
%% mgrpbroadcasterpolicy: NO_REQUIREMENTS
%% mgrpmsgrejectaction: REPLY
%% objectclass: top
%% objectclass: groupofuniquenames
%% objectclass: groupofurls
%% objectclass: mailgroup
%% objectclass: mailgroupmanagement
%% memberurl: ldap:///o=vtc.edu.hk??sub?(| (uid=hmpoon) (uid=flofung)(uid=joeytan
%% g))
%% mailhost: hqmail.vtc.edu.hk
%% mgrpallowedbroadcaster: uid=flofung,ou=ITSD,o=vtc.edu.hk
%% mgrpallowedbroadcaster: uid=hmpoon,ou=ITSD,o=vtc.edu.hk
%% mgrpallowedbroadcaster: uid=joeytang,ou=ITSD,o=vtc.edu.hk
%% # search result
%% search: 2
%% result: 0 Success
%% # numResponses: 2
%% # numEntries: 1
%% \item Refer to section~\vref{sec:auth_ldap}, and read the
%% documentation for \texttt{mod\_auth\_ldap} and \texttt{mod\_ldap},
%% and configure Apache so that one web directory is accessible only to
%% staff or students in your group.
%% Note: test your filter first using \texttt{ldapsearch}. Write your
%% \LDAP \URL here:
%% \begin{biganswerbox}
%% \begin{solution}%
%% \texttt{ldap://ldap.vtc.edu.hk/dc=vtc.edu.hk?uid?sub?(|(\&(acType=STF*)\allowbreak(|(department=ICT)(department=CSEC)))(\&(acType=STU*)(department=ICT)\allowbreak(|(o=ftstudent)(o=ptstudent)(o=alumni))))}
%% \end{solution}
%% \end{biganswerbox}
%% Show your \URL to your tutor.
%% \item Create another web site on your machine and authenticate against
%% the \VTC \LDAP server, and authenticate a user if \emph{all of} the
%% following is true:
%% \begin{itemize*}
%% \item The account has an attribute \texttt{acType} that starts with
%% \texttt{STF} AND
%% \item The account has an attribute \texttt{department} that is
%% EITHER equal to \texttt{ICT} OR that is equal to \texttt{CSEC}
%% \end{itemize*}
%% \vspace*{-0.5\baselineskip}
%% OR:
%% \vspace*{-0.5\baselineskip}
%% \begin{itemize*}
%% \item The account has an attribute \texttt{acType} that starts with
%% \texttt{STU} AND
%% \item The account has an attribute \texttt{department} that is
%% equal to \texttt{ICT} AND
%% \item The account has an attribute \texttt{o} that is equal to
%% \texttt{ftstudent} OR that is equal to \texttt{ptstudent} OR that is
%% equal to \texttt{alumni}.
%% \end{itemize*}
%% Make sure that you test your filter using \texttt{ldapsearch}
%% first. Write your \LDAP \URL here:
%% \begin{biganswerbox}
%% \begin{solution}%
%% \texttt{ldap://ldap.vtc.edu.hk/dc=vtc.edu.hk?uid?sub?(|(\&(acType=STF*)\allowbreak
%% (|(department=ICT)(department=CSEC)))(\&(acType=STU*)(department=ICT)\allowbreak
%% (|(o=ftstudent)(o=ptstudent)(o=alumni))))}
%% \end{solution}
%% \end{biganswerbox}
%% %% \answerbox[.6\columnwidth]{%
%% %% \texttt{ldap://ldap.tyict.vtc.edu.hk/dc=vtc.ddu.hk?uid?sub?(|(&(acType=STF*)(|(department=ICT)(department=CSEC)))(&(acType=STU*)(department=ICT)(|(o=ftstudent)(o=ptstudent)(o=alumni))))}
%% %% }
%% \s{%
%% \textbf{Solution}\\
%% Create a directory \texttt{/var/www/html/staff-or-students}. Then
%% create an entry in your web server configuration like this:\\
%% \texttt{%
%% \small
%% \\
%% \hspace*{3em}AuthType Basic\\
%% \hspace*{3em}AuthName "LDAP authentication to staff or group V of year
%% 3 CSA only"\\
%% \hspace*{3em}AuthLDAPURL ldap://ldap.tyict.vtc.edu.hk/ou=People,dc=tyict,dc=vtc,\\
%% dc=edu,dc=hk?uid?one?(\textbar(acType=STF)(\&(course=41300)(year=3)(classCode=V)))\\
%% \hspace*{3em}require valid-user\\
%%
%% }\\
%% And there you go, it'll work.
%% }
\end{enumerate}
\end{document}