\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#120: Restricted DDE Services}
\date{December 04, 2002}
\author{Pat Thoyts}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#120}&\textbf{Restricted DDE Services}\\\hline
Author&

Pat Thoyts \tipmail{patthoyts}{users.sourceforge.net}
\\
Created&Wednesday, \(\text{4}^{\text{th}}\) December 2002\\
Type&Project\\
Tcl Version&\(8.5\)\\
State&Final\\
Vote&Done\\
Version&\tipversion$Revision: 1.5 $\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This TIP will enhance the DDE package for use with safe interpreters and allow programmer control of the commands exposed by the DDE service.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Rationale}

By default the Tcl DDE service exposes all of the commands and variables available in the interpreter to all DDE clients. This is not always desirable. One solution might be to load the package into a safe slave interpreter and use [interp alias] to expose the required commands. Unfortunately the package doesn't support loading into safe interpreters.

\section{Proposed Changes}

Firstly, this TIP proposes a \textit{-handler} option to the [dde servername] sub-command. The argument for this option should be the name of a procedure that will authenticate and evaluate DDE requests.

Secondly, the DDE package should be enhanced to be capable of providing a service within a safe interpreter.

\section{New Option}

The new syntax will be \textit{dde servername ?-handler command? servername}. To permit introspection we will accept \textit{dde servername -handler} which will return the handler name (if any). If a servername must be defined using an initial hyphen then the standard '-{}-' separator can be used.

The dde request is appended to the handler command (which may be a list) and then evaluated in the global context. This ensures that all unsafe elements will not be evaluated before the handler code has a chance to examine them. So
\begingroup\small\begin{verbatim}
 proc handler {request} {
    if {[string match "info *" $request} {
       uplevel #0 [lindex $request 0] [lrange $request 1 end]
    } else
       return -code error "permission denied"
    }
 }
\end{verbatim}
\endgroup

The above handler will permit [info vars] but will fail when trying [info vars ; bad\_proc] with info complaining about the wrong number of parameters. Passing a single string means that we can handle standard dde styles of requests, for instance 'Open(``c:\(\backslash\)Program Files\(\backslash\)prog.exe'')' which would not usefully convert into a list.

\section{Safe DDE}

The dde package should support loading within a safe interpreter but with the following constraints.
\begin{itemize}
\item{}
The dde command should be hidden. This means that the safe interpreter may not call the command but a master interpreter call this command within the context of the safe interpreter.
\item{}
Remote execution requests should be handled \textit{only} by a defined handler procedure. The normal default is to evaluate a remote execution request in the global namespace. I propose that when operating in a safe interpreter that the request be denied unless a handler is defined. The programmer then has the ability to authenticate the request before it is evaluated.
\item{}
Remote variable reads should be denied. Rather that add in another handler --- the XTYP\_REQUEST service command should be denied for safe interpreters. It is trivial to use [dde eval Remote set \$varname] to read the value of a variable.
\end{itemize}

\section{Reference Implementation}

See the SourceForge Feature Request at \url{https://sourceforge.net/tracker/index.php?func=detail&aid=649859&group_id=10894&atid=310894}

\section{Example}
\begingroup\small\begin{verbatim}
 # Provide a handler that only allows the [info] command
 # Note: This runs in the master interp.
 proc restricted_handler {request} {
    if {[string match "info *" $request} {
       uplevel #0 [lindex $request 0] [lrange $request 1 end]
    } else
       return -code error "permission denied"
    }
 }

 # Create a safe slave interpreter and expose as a DDE service.
 safe::interpCreate slave
 slave invokehidden load tcldde12d.dll Dde
 slave invokehidden dde servername -handler dde_cmd SafeSlave
 interp alias slave dde_cmd {} restricted_handler

 # If testing in tclsh...
 set ::_waiting 0 ; after 20000 {set ::_waiting 1} ; vwait ::_waiting
\end{verbatim}
\endgroup

\section{Consequences}

There should be no change to current users of this package unless they are using a server name beginning with a hyphen. In this case they will need to insert '-{}-' before the server name.

\section{Copyright}

This document is hereby placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\end{document}
