Remove the "tls_use_crl" configuration parameter.
[pwmd.git] / doc / pwmd.texi
blobfbf8717d36da4fdd07ccd8148d89125c773ccaee
1 \input texinfo @c -*-texinfo-*- 
2 @c %**start of header 
3 @setfilename pwmd.info 
4 @settitle PWMD Manual
5 @c %**end of header
7 @dircategory Miscellaneous
8 @direntry
9 * pwmd: (pwmd).         Password Manager Daemon
10 @end direntry
12 @titlepage 
13 @title PWMD Manual
14 @subtitle Commands and syntax
15 @author by Ben Kibbey
16 @end titlepage
18 @c    Node, Next, Previous, Up 
19 @node Top ,     ,         , (dir) 
21 @ifinfo 
22 This manual documents @command{pwmd} version 3.0 protocol commands and
23 their syntax.
24 @end ifinfo 
26 @menu 
27 * Introduction::          Overview of pwmd.
28 * Invoking::              Command line options.
29 * Configuration::         Configuration file options.
30 * Commands::              Protocol commands.
31 * Status Messages::       Status lines and their meaning.
32 * Target Attribute::      A kind of symbolic link.
33 * Concept Index::         Index of concepts.
34 @end menu
36 @c    Node,     Next,    Previous, Up 
37 @node Introduction, Invoking,        , Top 
38 @chapter Overview of @command{pwmd} 
40 @command{pwmd} or @dfn{Password Manager Daemon} is a server that
41 applications connect to and send commands to store and retrieve data
42 that is saved in an encrypted @abbr{XML} document.
44 The server uses the Assuan protocol (@inforef{Implementation,,assuan}) which
45 is the same used by @command{gpg-agent}, @command{pinentry} and
46 @command{scdaemon}. It also uses @cite{libgpg-error} for error reporting with
47 the error source set as @var{GPG_ERR_SOURCE_USER_1}.
49 The @abbr{XML} document uses the following @abbr{DTD}:
51 @example
52     <?xml version="1.0"?>
53     <!DOCTYPE pwmd [
54     <!ELEMENT pwmd (element*)>
55     <!ATTLIST element _name CDATA #REQUIRED>
56     ]>
57 @end example
59 The @code{pwmd} element is the document root node while all other elements
60 of the document have the name @code{element} with an attribute @code{_name}
61 whose value uniquely identifies the element at the current element tree depth.
62 It is done this way to avoid @abbr{XML} parsing errors for commonly used
63 characters.  A @abbr{URL} for example would be an invalid @abbr{XML} element
64 since the @abbr{URI} contains a @samp{:} which is also the @abbr{XML}
65 namespace separator.
67 As mentioned, an element name must be unique for the current element tree
68 depth. You cannot have two elements containing the same @code{_name} attribute
69 value. @command{pwmd} will stop searching for an element of an @emph{element
70 path} at the first match then continue searching for the next element of the
71 element path beginning at the child node of the matched element.
73 An @emph{element path} is a @key{TAB} delimited character string where each
74 @key{TAB} separates each element in the path.  For example, the element path
75 @code{a@key{TAB}b@key{TAB}c} has the following @abbr{XML} document structure:
77 @example
78         <pwmd>
79             <element _name="a">
80                 <element _name="b">
81                     <element _name="c">
82                         [... element value or content ...]
83                     </element>
84                 </element>
85             </element>
86         </pwmd>
87 @end example
89 The only restriction of an element name is that it contain no whitespace
90 characters. It also cannot begin with a @samp{!} since this character is
91 reserved for the @code{target} attribute. @xref{Target Attribute}.
93 @c    Node,     Next,    Previous, Up 
94 @node Invoking, Configuration, Introduction, Top 
95 @chapter Invoking @command{pwmd} 
97 Since @command{pwmd} uses @command{gpg-agent} for key generation, decryption,
98 signing and caching of passphrases, @command{gpg-agent} must be running prior
99 to @command{pwmd} startup. The @env{GPG_AGENT_INFO} environment variable is
100 set by @command{gpg-agent} and @command{pwmd} uses this variable to determine
101 where the @command{gpg-agent} socket is listening for connections.
103 It is recommended to pass the @option{--allow-preset-passphrase}
104 command line option to @command{gpg-agent}. Doing so allows @command{pwmd}
105 cache pushing on startup. It is also recommended to pass the
106 @option{--allow-loopback-pinentry} to @command{gpg-agent}. This option allows
107 a passphrase to be inquired from @command{pwmd} when a @command{pinentry} is
108 unavailable to the client.
110 The exception to using @command{gpg-agent} is passing the option
111 @option{--no-agent} to @command{pwmd}. This prevents the need of
112 @command{gpg-agent} entirely but also limits @command{pwmd} to use
113 symmetrically encrypted data files.
115 @cindex Running @command{pwmd} 
116 @command{pwmd} is executed as follows: 
118 @example 
119 pwmd @var{options} [ file1 ] [ @dots{  } ]
120 @end example
122 Non-option arguments are data files to cache on startup. When the data file
123 requires a passphrase for decryption a @command{pinentry} will prompt either
124 on the current @abbr{TTY} or from an X11 window when the @env{DISPLAY}
125 environment variable is set.
127 @cindex Options 
128 @cindex Arguments 
129 The following command line options are supported:
131 @cindex Getting help 
132 @table @samp 
133 @item --homedir directory
134 The root directory where pwmd will store its data and temporary files.  The
135 default is @file{~/.pwmd}.
137 @item --rcfile, -f rcfile
138 Specify an alternate configuration file. The default is
139 @file{~/.pwmd/config}.
141 @item --no-agent
142 Disable the use of @command{gpg-agent}. This removes support for
143 public/private key encrypted data files. Files previously handled by
144 @command{gpg-agent} will no longer be able to be opened when this option
145 is specified. New data files are symmetrically or conventionally
146 encrypted and without a public and private key. When not specified, both
147 data file types are supported unless option @option{--disable-agent} was
148 passed to @command{configure} at compile time.
150 @item --import, -I filename
151 Imports an @abbr{XML} file. The @abbr{XML} file should be in conformance to
152 the @command{pwmd} @abbr{DTD} (@pxref{Introduction}). You
153 will be prompted for a passphrase to encrypt with.  The output is written to
154 the filename specified with @option{--outfile}. To make use of the imported
155 data, place the output file in @file{~/.pwmd/data}.
157 @item --keyparam S-expression
158 The key parameters to use when generating a new key pair while importing an
159 @abbr{XML} file or when converting a @emph{version 2} data file. The argument
160 must be a valid S-expression (@inforef{S-expressions,, gcrypt}).
162 @item --keygrip hexstring
163 Specifies the hexadecimal encoded public key-grip to use for encryption when
164 importing or converting. When not specified a new key-pair will be created.
166 @item --sign-keygrip hexstring
167 Specifies the hexadecimal encoded public key-grip to use for signing of the
168 data file when importing or converting. When not specified the generated
169 public key or the key specified with the @option{--keygrip} option will be
170 used.
172 @item --passphrase-file, -k filename"
173 Obtain the passphrase from the specified filename.
175 @item --s2k-count iterations
176 The number of times to hash the passphrase when importing or converting.  The
177 default is the gpg-agent calibrated value of the machine. When less than
178 @samp{65536} the default will be used.
180 @item --cipher-iterations iterations
181 The number of symmetric encryption iterations. The value is actually N+1. The
182 default is 0+1.
184 @item --cipher algo
185 When importing, the cipher to use for data encryption.  See the @var{cipher}
186 configuration parameter (@pxref{Configuration}) for available ciphers. The
187 default is @samp{aes256}.
189 @item --convert, -C filename
190 Converts a @command{pwmd} @emph{version 2} data file to a @emph{version 3}
191 data file. If encrypted, you will be prompted for a passphrase to use for
192 decryption unless @option{--passphrase-file} was specified. The converted data
193 file will be saved to the filename specified with @option{--outfile}. All
194 @option{--import} related options may also be used when converting.
196 @item --disable-dump, -D
197 Disable the @code{XPATH}, @code{XPATHATTR}, @code{LIST} and @code{DUMP}
198 protocol commands (@pxref{Commands}). This overrides any
199 @var{disable_list_and_dump} configuration parameter (@pxref{Configuration}).
201 @item --no-fork, -n
202 Run as a foreground process and do not fork into the background.
204 @item --ignore
205 Ignore cache pushing failures on startup. By default, @command{pwmd} will exit
206 if an error occurred do to an invalid passphrase or other error.
208 @item --debug-level keyword,keyword,...
209 Output libassuan @inforef{Top,,assuan} protocol IO with the comma
210 separated list of output keywords.  Valid keywords are: @code{init},
211 @code{ctx}, @code{engine}, @code{data}, @code{sysio} and @code{control}.
213 @item --version
214 Show the version, copyright and compile time features and exit.
216 @item --help 
217 Print a summary of options.
218 @end table
220 @cindex Signals
221 Sending the @emph{SIGHUP} signal to a @command{pwmd} process will reload the
222 configuration file and sending @emph{SIGUSR1} will clear the entire file
223 cache.
225 @c    Node,     Next,    Previous, Up 
226 @node Configuration, TLS, Invoking, Top 
227 @chapter @command{pwmd} configuration options
228 If no configuration file is specified with the @command{pwmd} @option{-f}
229 command line option, @command{pwmd} will read @file{~/.pwmd/config} if it
230 exists, and if not, will use defaults.  Blank lines and lines beginning with
231 @samp{#} are ignored. Some parameters may have data file specific settings by
232 placing them in a file section. A file section is declared by surrounding the
233 filename with braces (i.e., @samp{[filename]}).  Global options may be
234 specified in a @samp{[global]} section and are the default options for new or
235 unspecified files.
237 A tilde @key{~} will be expanded to the home directory of the invoking user
238 when contained in a parameter whose value is a filename.
240 @cindex Reloading the configuration file
241 The configuration file can be reloaded by sending the @emph{SIGHUP} signal to
242 a @command{pwmd} process.
244 @cindex Global configuration options
245 The following options are only for use in the @samp{global} section:
247 @table @samp 
248 @item socket_path = /path/to/socket
249 Listen on the specified socket. The default is @file{~/.pwmd/socket}.
251 @item socket_perms = octal_mode
252 Permissions to set after creating the socket. This will override any
253 @cite{umask(2)} setting.
255 @item allowed = user,@@group,...
256 A comma separated list of local user names or group names allowed to connect
257 to the socket. Groups should be prefixed with a @samp{@@}. When not specified
258 only the invoking user may connect.
260 @item disable_mlockall = boolean
261 When set to @var{false}, @cite{mlockall(2)} will be called on startup.  This
262 will use more physical memory but may also be more secure since no swapping to
263 disk will occur. The default is @var{true}.
265 @item log_path = /path/to/logfile
266 Logs informational messages to the specified file. The default is
267 @file{~/.pwmd/log}.
269 @item enable_logging = boolean
270 Enable or disable logging to @var{log_path}. The default is @code{false}.
272 @item syslog = boolean
273 Enable logging to @cite{syslog(8)} with facility @emph{LOG_DAEMON} and priority
274 @emph{LOG_INFO}. The default is @code{false}.
276 @item log_level = level
277 When @code{0}, only connections and errors are logged. When @code{1}, client
278 commands are also logged. When @code{2}, the command arguments are also logged.
279 The default is @code{0}.
281 @item agent_env_file = filename
282 A file containing the @env{GPG_AGENT_INFO} environment variable and value as
283 output by the @command{gpg-agent} @option{--write-env-file} command line
284 option.
286 @item kill_scd = boolean
287 Kill @command{scdaemon} after each @code{OPEN} (@pxref{OPEN}) or @code{SAVE}
288 (@pxref{SAVE}) command.
290 @item disable_list_and_dump = boolean
291 When @code{true}, the @code{XPATH}, @code{XPATHATTR}, @code{LIST} and
292 @code{DUMP} protocol commands (@pxref{Commands}) will be disabled.
294 @item cache_push = file1,file2
295 A comma separated list of filenames that will be pushed into the file cache
296 upon startup. @command{pwmd} will prompt for the passphrase for each file unless
297 specified with the @var{passphrase} or @var{passphrase_file} parameters in a
298 matching file section.
300 @item priority = integer
301 The priority, or niceness, of the server. The default is inherited from the
302 parent process.
304 @item cipher = algorithm
305 The default cipher to use for data encryption. The algorithm must be one of:
306 @code{aes128}, @code{aes192}, @code{aes256}, @code{serpent128},
307 @code{serpent192}, @code{serpent256}, @code{camellia128},
308 @code{camellia192}, @code{camellia256}, @code{3des}, @code{cast5},
309 @code{blowfish}, @code{twofish128} or @code{twofish256}. The default is
310 @code{aes256}.
312 @item cipher_iterations = integer
313 The number of times to encrypt the XML data. This differs from the
314 @var{s2k_count} parameter which specifies the number of times to hash the
315 passphrase used to encrypt the data. The default is 0 although 1 iteration is
316 still done.
318 @item cipher_progress = integer
319 Send a progress message to the client after the specified amount of encryption
320 or decryption iterations have been done. The default is 2000.
322 @item algo = algorithm
323 The default algorithm to use when generating a new key-pair. The default is
324 @code{rsa}.
326 @item nbits = bits
327 The default number of bits to use when generating a new key-pair. The default
328 is @code{2048}.
330 @item pinentry_path = /path/to/pinentry
331 The location of the @command{pinentry} binary. This program is used to
332 prompt for a passphrase when not using @command{gpg-agent}. The default
333 is specified at compile time.
335 @item pinentry_timeout = seconds
336 The number of seconds to wait for a pinentry before giving up and
337 returning an error. This timeout value is used for both waiting for
338 another pinentry to complete and for the pinentry waiting for user input.
339 @end table
341 @cindex Data file configuration options
342 The following options are defaults for new files when specified in the
343 @samp{global} section. When placed in a data file section they are options
344 specific to that data file only.
346 @table @samp 
347 @item backup = boolean
348 Whether to create a backup of the data file when saving. The backup filename
349 has the @file{.backup} extension appended to the opened file. The default is
350 @code{true}. 
352 @item cache_timeout = seconds
353 The number of seconds to keep the cache entry for this file. If @code{-1}, the
354 cache entry is kept forever. If @code{0}, each time an encrypted file is
355 @code{OPEN}ed (@pxref{OPEN}) a passphrase will be required. The default
356 is @code{-1}.
358 @item xfer_progress = bytes
359 Commands that send data lines to the client will also send the @code{XFER}
360 status message (@pxref{Status Messages}) after the specified number of bytes
361 have been sent. The number of bytes is rounded to @var{ASSUAN_LINELENGTH} or
362 @code{1002} bytes. The default is @code{8196}.
364 @item passphrase = string
365 The passphrase to use for this file. If specified in the @samp{global} section
366 then @samp{global} is treated as a data filename and not a default for other
367 files. Note that if a client changes the passphrase for this data file then
368 this value is not modified and will need to be updated.
370 @item passphrase_file = /path/to/file
371 Same as the @var{passphrase} parameter above but obtains the passphrase from
372 the specified filename.
374 @item recursion_depth = integer
375 The maximum number of times to resolve a @code{target} attribute for an
376 element in an element path (@pxref{Target Attribute}). An error is returned
377 when this value is exceeded.  The default is @code{100} but can be disabled by
378 setting to @code{0} (@emph{not recommended}).
380 @end table
381 @menu
382 * TLS::                   Remote connections over TLS.
383 * Pinentry::              Configuration file and defaults.
384 @end menu
386 @node TLS, Pinentry, Configuration, Configuration
387 @chapter Configuring remote connections over TLS.
388 Remote connections can be made to @command{pwmd} over @abbr{TLS}.
389 Authentication is done by using X509 client certificates that are signed with
390 the same Certificate Authority (@abbr{CA}) as the server certificate.
392 The @abbr{CA} certificate is expected to be found in
393 @file{~/.pwmd/ca-cert.pem} while the @command{pwmd} server certificate and key
394 file should be put in @file{~/.pwmd/server-cert.pem} and
395 @file{~/.pwmd/server-key.pem}, respectively.
397 See the documentation of @command{certtool} or @command{openssl} for details
398 on creating self-signed certificates.
400 The following TLS configuration options are available:
402 @table @samp 
403 @item enable_tcp = boolean
404 Whether to enable TCP/TLS server support. If enabled, both TCP and the local
405 unix domain socket will listen for connections. The default is
406 @code{false}.
408 @item tcp_port = integer
409 The TCP port to listen on when @var{enable_tcp} is @code{true}. The default is
410 @code{6466}.
412 @item tcp_bind = string
413 The internet protocol to listen with. Must be one of @code{ipv4}, @code{ipv6}
414 or @code{any} to listen for both IPv4 and IPv6 connections.
416 @item tcp_interface = string
417 Only useful if running as root.
419 @item tls_timeout = seconds
420 The number of seconds to wait for a read() or write() call on a
421 @abbr{TLS} client file descriptor to complete before returning an
422 error. The default is @var{300}.
424 Note that the @code{SAVE} command (@pxref{SAVE}), when used with
425 @command{gpg-agent}, may take a longer time to complete than other
426 commands when creating a new file since a key-pair will need to be
427 generated.
429 @item keepalive_interval = seconds
430 Send a keepalive status message to an idle remote client.  An idle
431 client is one who is not in a command. The purpose of this status
432 message is to disconnect a hung remote client and release any file mutex
433 locks so another client may open the same data file.
435 @item tls_access = string[,string,...]
436 A comma separated list of client X509 certificate fingerprints in SHA-1
437 format that will be allowed to connect or open a file. If prefixed with
438 @code{!} then access is denied for the fingerprint. When @code{!} is
439 found by itself in the list it is treated as a default for remaining
440 fingerprints in the list. The @code{+} prefix behaves the same but
441 allows access.
443 The access control is two fold: when the client connects its SHA-1
444 fingerprint is matched against the list of allowed fingerprints in the
445 @samp{global} section. When allowed in the @samp{global} section the
446 connection is established and the client may proceed to @code{OPEN}
447 (@pxref{OPEN}) a data file. During the @code{OPEN} command the
448 fingerprint is checked again in a @samp{filename} section. When this
449 parameter is not found in a @samp{filename} section then access is granted.
451 @item tcp_require_key = boolean
452 When @code{true}, require the remote client to provide the key or passphrase
453 to open a data file even if the file is cached. Note that the cache entry is
454 cleared during the @pxref{OPEN} command and the passphrase will be retrieved
455 from the client via a server @emph{INQUIRE}. This option is a default
456 for all files when specified in the @samp{global} section. The default
457 is @code{false}.
459 @item tcp_wait = integer
460 The time in tenths of a second to wait between TCP connections.  Setting to 0
461 will disable waiting. The default is @code{3}.
463 @item tls_cipher_suite = string
464 The GnuTLS cipher suite and protocol to use. See the GnuTLS documentation for
465 information about the format of this string. The default is @code{SECURE256}.
466 @end table
468 @node Pinentry, Commands, TLS, Configuration
469 @chapter Pinentry configuration
470 The @command{pinentry} program is used to prompt the user for passphrase
471 input or as a confirmation dialog; it needs to know where to prompt for
472 the input, beit from a terminal or an X11 display.
474 It is the responsibility of the client to tell @command{pinentry} about
475 the terminal or X11 display before requiring the input. This is done by
476 using the @command{pwmd} @pxref{OPTION} protocol command. It need be
477 done only once per client connection. To avoid the use of
478 @command{pinentry} entirely, use @code{OPTION} (@pxref{OPTION})
479 @option{--disable-pinentry}.
481 @c    Node,     Next,    Previous, Up
482 @node Commands, Status Messages, Pinentry, Top
483 @chapter Protocol commands and their syntax
484 @include menu.texi
485 @include commands.texi
487 @c    Node,     Next,    Previous, Up 
488 @node Status Messages, Target Attribute, Commands, Top 
489 @chapter Status messages and their meanings
490 Some commands send status messages to inform the client about certain
491 operations or as a progress indicator.  Status messages begin with a
492 @code{KEYWORD} followed by a status description for status messages that
493 require it. What status messages are sent, when, and how often depend on
494 configuration settings (@pxref{Configuration}). A status message sent from
495 @command{gpg-agent} (@inforef{Invoking GPG-AGENT,,gnupg}) is also forwarded to
496 the client.
498 @multitable @columnfractions .20 .25 .55
499 @headitem Message @tab Arguments @tab Description
500 @item CACHE
501 @cindex CACHE
502 @tab @code{<integer>}
503 @tab The number of cached documents. Sent to each client after connecting
504 (@pxref{GETINFO}) and after every cache modification.
506 @item CLIENTS
507 @cindex CLIENTS
508 @tab @code{<integer>}
509 @tab The number of connected clients (@pxref{GETINFO}). Sent to each client
510 when another client either connects or disconnects.
512 @item DECRYPT
513 @cindex DECRYPT
514 @tab @code{n} @code{total}
515 @tab Sent to the current client during a decrypt operation. How often this
516 status message is sent is determined by the @code{cipher_progress}
517 (@pxref{Configuration}) setting.
519 @item ENCRYPT
520 @cindex ENCRYPT
521 @tab @code{n} @code{total}
522 @tab Sent to the current client during an  encrypt operation. How often this
523 status message is sent is determined by the @code{cipher_progress}
524 (@pxref{Configuration}) setting.
526 @item GENKEY
527 @cindex GENKEY
528 @tab
529 @tab Sent once to the current client just before generating a new key-pair.
531 @item INQUIRE_MAXLEN
532 @cindex INQUIRE_MAXLEN
533 @tab @code{<bytes>}
534 @tab Sent to the client from @command{gpg-agent} when inquiring data. This
535 specifies the maximum number of bytes allowed for the client to send and
536 should not be exceeded.
538 @item KEEPALIVE
539 @cindex KEEPALIVE
540 @tab
541 @tab Sent to each idle client every @var{keepalive_interval}
542 (@pxref{Configuration}) seconds.
544 @item LOCKED
545 @cindex LOCKED
546 @tab
547 @tab Sent to the current client when another client is holding the lock for
548 the mutex associated with a file.
550 @item NEWFILE
551 @cindex NEWFILE
552 @tab
553 @tab Sent to the current client when the opened (@pxref{OPEN}) file does not
554 exist on the file-system.
556 @item XFER
557 @cindex XFER
558 @tab @code{<sent> <total>}
559 @tab Sent to the current client when transferring data. It has two space
560 delimited arguments. The first being the current amount of bytes transferred
561 and the other being the total bytes to be transferred.
562 @end multitable
564 @c    Node,     Next,    Previous, Up 
565 @node Target Attribute, Concept Index, Status Messages, Top 
566 @chapter The @code{target} attribute
567 @cindex target attribute
568 A @emph{case sensitive} attribute named @code{target} is treated specially
569 when found in each element of an element path. This attribute, like other
570 element attributes, is created or modified with the @code{ATTR} command
571 (@pxref{ATTR}). The value of this attribute is an existing element path
572 somewhere in the document.  If you are familiar with @abbr{XML} entities or
573 maybe the @abbr{HTML} @code{id} or @code{target} attributes or a symbolic link
574 in a file-system, you may find this attribute behaves similar to any of those.
576 To create a @code{target} attribute use the following syntax:
578 @example
579 ATTR SET target [!]element[@key{TAB}[!]child[..]] [!]element[@key{TAB}[!]child[..]]
580 @end example
582 Note the single space between the two element paths. The first element path is
583 where the @code{target} attribute will be created. If the element path does
584 not exist then it will be created.  This is the only time the @code{ATTR}
585 (@pxref{ATTR}) command will create elements. The attribute is created in the
586 final element of the element path.
588 The second element path is the destination of where you want the first element
589 path to resolve to. When an element path is passed to a protocol command
590 @command{pwmd} looks for a @code{target} attribute when resolving each element
591 and if found, "jumps" to the attribute value and continues resolving any
592 remaining elements.  When you want to avoid the @code{target} attribute for
593 any element of an element path then prefix the element with the literal
594 element character @samp{!}.
596 When an element of a element path is removed that a @code{target} attribute
597 resolves to then an error will occur. You may need to either update the
598 @code{target} attribute value with a new element path or remove the attribute
599 entirely. Remember that since the element contains the @code{target} attribute
600 it will need to be prefixed with the literal element character @samp{!} when
601 specifying the element path. For example, to remove a @code{target}
602 attribute for an element containing it:
604 @example
605 ATTR DELETE target path@key{TAB}to@key{TAB}!element
606 @end example
608 Clients should be careful of creating @code{target} loops, or targets that
609 resolve to themselves. See the @var{recursion_depth} (@pxref{Configuration})
610 configuration parameter for details.
612 The @code{REALPATH} command (@pxref{REALPATH}) can be used to show the element
613 path after resolving all @code{target} attributes.
616 @c    Node,     Next,    Previous, Up 
617 @node Concept Index, , Target Attribute, Top 
618 @unnumbered Concept Index
620 @printindex cp
621 @shortcontents 
622 @contents 
623 @bye