%\documentclass{ictlab}
\documentclass[solutions]{ictlab}

\RCS $Revision: 1.16 $

\usepackage{verbatim,key,alltt,amstext,answer2,biganswerbox}
\usepackage[hang,bf,nooneline]{caption2}
\ifx\pdftexversion\undefined \else
  \usepackage[pdfpagemode=None,pdfauthor={Nick Urbanik}]{hyperref}
\fi

\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}
<Location "/staff">
     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
</Location>
\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 \emph{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 V, 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\}'}
Wu Sze-wai
Cheung Chun-wah
Cheung Man-fai
Tsang Man-kit
Li Cho-tim
Law Suk-man, Annie
Chan Wan-fung
Kong Kwok-kay
Mak Yiu-wai
Lam Chi-wai
Pui Yuen-ting
Lau Kin-pong
Lo Ho-man
Fung Ka-keung, Terry
Tam Wai-sze
Chan Kit-ming
Au Wai-yin
Wong Chun-po, Ray
Chui Hoi-yan
Chan Sui-nam
\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}286}
  }%
  
\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
<Location "/staff-or-students">\\
\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\\
</Location>
}\\
And there you go, it'll work.
}
\end{enumerate}

\end{document}
