keys.*: Enforce separation between user's files and the system.
[distorted-keys] / keys.keeper-cards
1 #! /bin/sh
2 ###
3 ### Issue cards containing a bunch of keeper secrets
4 ###
5 ### (c) 2011 Mark Wooding
6 ###
7
8 ###----- Licensing notice ---------------------------------------------------
9 ###
10 ### This file is part of the distorted.org.uk key management suite.
11 ###
12 ### distorted-keys is free software; you can redistribute it and/or modify
13 ### it under the terms of the GNU General Public License as published by
14 ### the Free Software Foundation; either version 2 of the License, or
15 ### (at your option) any later version.
16 ###
17 ### distorted-keys is distributed in the hope that it will be useful,
18 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ### GNU General Public License for more details.
21 ###
22 ### You should have received a copy of the GNU General Public License
23 ### along with distorted-keys; if not, write to the Free Software Foundation,
24 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26 set -e
27 case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
28 . "$KEYSLIB"/keyfunc.sh
29
30 defhelp <<HELP
31 KEEPER [INDICES ...]
32 Typeset cards for a set of keeper secrets.
33
34 This program writes a PostScript file to standard output which will contain
35 key nubs from the keeper set KEEPER, specifically the keys with the given
36 INDICES. Elements of the list are either simple integers or ranges
37 [LOW]-[HIGH]; if LOW is omitted, it means 0, and if HIGH is omitted, it means
38 the highest possible index. If no INDICES are given then all secret keys are
39 written.
40
41 The public keys are found in $KEYS/keeper/KEEPER/I.pub;
42 key nubs are read from the safe place where \`keys new-keeper' left
43 them.
44 HELP
45
46 ## Parse the command line.
47 case $# in 0) usage_err ;; esac
48 keeper=$1; shift
49 checkword "keeper set label" "$keeper"
50
51 ## Find out about the set.
52 if [ ! -f $KEYS/keeper/$keeper/meta ]; then
53 echo >&2 "$quis: unknown keeper set \`$keeper'"
54 exit 1
55 fi
56 read n hunoz <$KEYS/keeper/$keeper/meta
57
58 ## Check that nubs are available for the keeper set.
59 reqsafe
60 if [ ! -d $SAFE/keys.keeper/$keeper/ ]; then
61 echo >&2 "$quis: no nubs available for keeper set \`$keeper'"
62 exit 1
63 fi
64 cd $SAFE/keys.keeper/$keeper/
65
66 ## Build a colon-separated list of the indices we actually want.
67 want=:
68 case $# in 0) set 0- ;; esac
69 for range in "$@"; do
70 case "$range" in
71 *[!-0-9]* | *[!0-9]*-* | *-*[!0-9]*)
72 echo >&2 "$quis: bad index range \`$range'"
73 exit 1
74 ;;
75 *-*)
76 low=${range%-*} high=${range#*-}
77 ;;
78 *)
79 low=$range high=$range
80 ;;
81 esac
82 case "$low" in ?*) ;; *) low=0 ;; esac
83 case "$high" in ?*) ;; *) high=$(( $n - 1 )) ;; esac
84 if [ 0 -gt $low -o $low -gt $high -o $high -ge $n ]; then
85 echo >&2 "$quis: invalid index range \`$range'"
86 exit 1
87 fi
88 i=$(( $low + 0 ))
89 while [ $i -le $high ]; do
90 case $want in *:"$i":*) ;; *) want=$want$i: ;; esac
91 i=$(( $i + 1 ))
92 done
93 done
94
95 ## Start working on the output file. This will contain deep secrets, so
96 ## don't leave stuff easily readable.
97 mktmp
98 umask 077
99 exec 3>$tmp/$keeper.tex
100 cat >&3 <<'EOF'
101 \documentclass[a4paper, landscape, 12pt]{article}
102 \usepackage[utf8]{inputenc}
103 \usepackage[T1]{fontenc}
104 \usepackage[palatino, helvetica, courier, maths = cmr]{mdwfonts}
105 \usepackage{graphicx}
106
107 %% Report errors with enough context that we can debug them.
108 \errorcontextlines=999
109
110 %% Basic layout for the cards. We use the paragraph filling machinery, but
111 %% don't actually need most of the trimmings.
112 \parindent=0pt
113 \parfillskip=0pt
114 \pagestyle{empty}
115
116 %% Page layout: try to use most of the page. The document class will already
117 %% have set up the paper size, but we do the rest here.
118 \hoffset=-1in \voffset=-1in
119 \oddsidemargin=20mm
120 \textwidth=\paperwidth \advance\textwidth by -2\oddsidemargin
121 \topmargin=20mm
122 \headheight=0pt \headsep=0pt
123 \textheight=\paperheight \advance\textheight by -2\topmargin
124 \AtBeginDocument{\special{papersize=\the\paperwidth,\the\paperheight}}
125
126 %% Parameters for the cards and guide rules.
127 \newdimen\cardwd \cardwd=82mm
128 \newdimen\cardht \cardht=49mm
129 \newdimen\guidelen \guidelen=10mm
130 \newdimen\rulewd \rulewd=0.6pt
131
132 %% Typesetting the secret as text. The macro \snarf TOKEN T0 T1 ... T7
133 %% gathers T0 T1 ... T7 into a single argument and passes them to TOKEN, as
134 %% long as T0 is not \relax. We use this to process the secret text in a
135 %% continuation-passing style.
136 \def\snarf#1#2{%
137 \ifx#2\relax\let\next\empty%
138 \else\def\next{\snarfdo#1#2}%
139 \fi%
140 \next%
141 }
142 \def\snarfdo#1#2#3#4#5#6#7#8#9{#1{#2#3#4#5#6#7#8#9}}
143
144 %% Print the left and right halves of the line, with a separator. Use boxes
145 %% for the lines so that TeX will work out the width of the enclosing vbox
146 %% for us. The basic usage is \line TEXT \relax ... \relax, with eight
147 %% \relax tokens: this is enough to complete both \snarf calls.
148 \def\line{\snarf\lineleft}
149 \def\lineleft#1{\hbox\bgroup#1 \snarf\lineright}
150 \def\lineright#1{#1\egroup\line}
151
152 %% Typeset a card containing a secret. Usage is \card{INDEX}{SECRET}.
153 \def\card#1#2{%
154 %%
155 %% Make sure we're setting a paragraph.
156 \leavevmode%
157 %%
158 %% Initial material: a stretchy space on the left.
159 \hbox{}\nobreak\hfil%
160 %%
161 %% An alignment for the guide markers surrounding the actual card.
162 \vbox{\halign{&##\cr%
163 %%
164 %% Top left guides.
165 \vrule width \guidelen height \rulewd depth 0pt%
166 \vrule width \rulewd depth 0pt height \guidelen%
167 &%
168 %%
169 %% Top centre gap.
170 \hfil%
171 &%
172 %%
173 %% Top right guides.
174 \vrule width \rulewd depth 0pt height \guidelen%
175 \vrule width \guidelen height \rulewd depth 0pt%
176 \cr%
177 %%
178 %% Left gap.
179 &%
180 %%
181 %% The actual card.
182 \vbox to \cardht{%
183 %%
184 %% We actually do more or less sensible typesetting. TeX will set the
185 %% box width from the hsize, and we should leave a small margin all
186 %% around.
187 \parfillskip=0pt plus 1fil%
188 \leftskip=1em \rightskip=1em%
189 \hsize=\cardwd%
190 %%
191 %% The heading.
192 \hrule height 0pt \prevdepth = 0pt%
193 \medskip%
194 {\large\bfseries\textsf{\keeper} secret #1/\total}%
195 %%
196 %% The QR-code and the text of the secret.
197 \vfil%
198 $%
199 \vcenter{\hbox{\includegraphics[scale = 2.4]{#1.eps}}}%
200 \hfil%
201 \vcenter{\ttfamily%
202 \line#2%
203 \relax\relax\relax\relax\relax\relax\relax\relax%
204 }%
205 $%
206 %%
207 %% And we're done.
208 \vfil%
209 }%
210 &%
211 %%
212 %% Right gap.
213 \cr%
214 %%
215 %% Bottom left guides.
216 \vrule width \guidelen depth \rulewd height 0pt%
217 \vrule width \rulewd depth \guidelen height 0pt%
218 &%
219 %% Bottom centre gap.
220 \hfil%
221 &%
222 %% Bottom right guides.
223 \vrule width \rulewd depth \guidelen height 0pt%
224 \vrule width \guidelen depth \rulewd height 0pt%
225 \cr%
226 %%
227 %% Leave a small vertical space at the bottom to separate lines of cards.
228 \strut \cr%
229 }}%
230 %%
231 %% End material: a stretchy space to match the one at the start, and then
232 %% allow a break.
233 \nobreak\hfil\hbox{}%
234 \penalty0%
235 }
236 EOF
237
238 ## Write the basic configuration stuff.
239 cat >&3 <<EOF
240
241 %% General configuration for the cards.
242 \def\keeper{$keeper}
243 \def\total{$n}
244 EOF
245
246 ## Start the document body.
247 cat >&3 <<'EOF'
248
249 %% The actual content.
250 \begin{document}
251 EOF
252
253 ## Work through the requested indices.
254 i=0
255 while [ $i -lt $n ]; do
256 case $want in
257 *:"$i":*)
258 read secret <$i
259 tr -d '\n' <$i | qrencode -m0 -s1 -o$tmp/$i.png
260 convert $tmp/$i.png $tmp/$i.eps
261 cat >&3 <<EOF
262 \card{$i}{$secret}
263 EOF
264 esac
265 i=$(( $i + 1 ))
266 done
267
268 ## Wrap up and build the document.
269 cat >&3 <<'EOF'
270 \end{document}
271 EOF
272 exec 3>&-
273 if ! (cd $tmp
274 exec </dev/null >tex.out 2>&1
275 latex $keeper.tex && dvips -o$keeper.ps $keeper.dvi); then
276 echo >&2 "$quis: document formatting failed"
277 sed >&2 's/^/| /' $tmp/tex.out
278 exit 1
279 fi
280 cat $tmp/$keeper.ps
281
282 ###----- That's all, folks --------------------------------------------------