3 # Copyright (c) 2002-2003 Networks Associates Technology, Inc.
6 # This software was developed for the FreeBSD Project by ThinkSec AS and
7 # Network Associates Laboratories, the Security Research Division of
8 # Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
9 # ("CBOSS"), as part of the DARPA CHATS research program.
11 # Redistribution and use in source and binary forms, with or without
12 # modification, are permitted provided that the following conditions
14 # 1. Redistributions of source code must retain the above copyright
15 # notice, this list of conditions and the following disclaimer.
16 # 2. Redistributions in binary form must reproduce the above copyright
17 # notice, this list of conditions and the following disclaimer in the
18 # documentation and/or other materials provided with the distribution.
19 # 3. The name of the author may not be used to endorse or promote
20 # products derived from this software without specific prior written
23 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 # $P4: //depot/projects/openpam/misc/gendoc.pl#30 $
42 use POSIX qw(locale_h strftime);
43 use vars qw($COPYRIGHT $TODAY %FUNCTIONS %PAMERR);
46 .\\\" Copyright (c) 2001-2003 Networks Associates Technology, Inc.
47 .\\\" All rights reserved.
49 .\\\" This software was developed for the FreeBSD Project by ThinkSec AS and
50 .\\\" Network Associates Laboratories, the Security Research Division of
51 .\\\" Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
52 .\\\" (\"CBOSS\"), as part of the DARPA CHATS research program.
54 .\\\" Redistribution and use in source and binary forms, with or without
55 .\\\" modification, are permitted provided that the following conditions
57 .\\\" 1. Redistributions of source code must retain the above copyright
58 .\\\" notice, this list of conditions and the following disclaimer.
59 .\\\" 2. Redistributions in binary form must reproduce the above copyright
60 .\\\" notice, this list of conditions and the following disclaimer in the
61 .\\\" documentation and/or other materials provided with the distribution.
62 .\\\" 3. The name of the author may not be used to endorse or promote
63 .\\\" products derived from this software without specific prior written
66 .\\\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
67 .\\\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68 .\\\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
69 .\\\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
70 .\\\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
71 .\\\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
72 .\\\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
73 .\\\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
74 .\\\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
75 .\\\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
78 .\\\" \$" . "P4" . "\$
82 PAM_SUCCESS => "Success",
83 PAM_OPEN_ERR => "Failed to load module",
84 PAM_SYMBOL_ERR => "Invalid symbol",
85 PAM_SERVICE_ERR => "Error in service module",
86 PAM_SYSTEM_ERR => "System error",
87 PAM_BUF_ERR => "Memory buffer error",
88 PAM_CONV_ERR => "Conversation failure",
89 PAM_PERM_DENIED => "Permission denied",
90 PAM_MAXTRIES => "Maximum number of tries exceeded",
91 PAM_AUTH_ERR => "Authentication error",
92 PAM_NEW_AUTHTOK_REQD => "New authentication token required",
93 PAM_CRED_INSUFFICIENT => "Insufficient credentials",
94 PAM_AUTHINFO_UNAVAIL => "Authentication information is unavailable",
95 PAM_USER_UNKNOWN => "Unknown user",
96 PAM_CRED_UNAVAIL => "Failed to retrieve user credentials",
97 PAM_CRED_EXPIRED => "User credentials have expired",
98 PAM_CRED_ERR => "Failed to set user credentials",
99 PAM_ACCT_EXPIRED => "User account has expired",
100 PAM_AUTHTOK_EXPIRED => "Password has expired",
101 PAM_SESSION_ERR => "Session failure",
102 PAM_AUTHTOK_ERR => "Authentication token failure",
103 PAM_AUTHTOK_RECOVERY_ERR => "Failed to recover old authentication token",
104 PAM_AUTHTOK_LOCK_BUSY => "Authentication token lock busy",
105 PAM_AUTHTOK_DISABLE_AGING => "Authentication token aging disabled",
106 PAM_NO_MODULE_DATA => "Module data not found",
107 PAM_IGNORE => "Ignore this module",
108 PAM_ABORT => "General failure",
109 PAM_TRY_AGAIN => "Try again",
110 PAM_MODULE_UNKNOWN => "Unknown module type",
111 PAM_DOMAIN_UNKNOWN => "Unknown authentication domain",
114 sub parse_source($) {
130 if ($fn !~ m,\.c$,) {
131 warn("$fn: not C source, ignoring\n");
135 sysopen(FILE, $fn, O_RDONLY)
136 or die("$fn: open(): $!\n");
137 $source = join('', <FILE>);
141 if ($source =~ m/^ \* NOPARSE\s*$/m);
144 $func =~ s,^(?:.*/)?([^/]+)\.c$,$1,;
145 if ($source !~ m,\n \* ([\S ]+)\n \*/\n\n([\S ]+)\n$func\((.*?)\)\n\{,s) {
146 warn("$fn: can't find $func\n");
149 ($descr, $type, $args) = ($1, $2, $3);
150 $descr =~ s,^([A-Z][a-z]),lc($1),e;
151 $descr =~ s,[\.\s]*$,,;
152 while ($args =~ s/^((?:[^\(]|\([^\)]*\))*),\s*/$1\" \"/g) {
155 $args =~ s/,\s+/, /gs;
162 if ($type eq "int") {
163 foreach (split("\n", $source)) {
164 next unless (m/^ \*\s+(!?PAM_[A-Z_]+|=[a-z_]+)\s*$/);
167 ++$xref{3}->{'pam_strerror'};
171 # extract names of regular arguments
172 $argnames =~ s/\"[^\"]+\*?\b(\w+)\"/\"$1\"/g;
173 # extract names of function pointer arguments
174 $argnames =~ s/\"([\w\s\*]+)\(\*?(\w+)\)\([^\)]+\)\"/\"$2\"/g;
175 # escape metacharacters (there shouldn't be any, but...)
176 $argnames =~ s/([\|\[\]\(\)\.\*\+\?])/\\$1/g;
177 # separate argument names with |
178 $argnames =~ s/\" \"/|/g;
179 # and surround with ()
180 $argnames =~ s/^\"(.*)\"$/($1)/;
181 # $argnames is now a regexp that matches argument names
182 $inliteral = $inlist = 0;
183 foreach (split("\n", $source)) {
185 if (!defined($man)) {
191 last if (m/^ \*\/$/);
195 if ($man ne "" && $man !~ m/\.Pp\n$/s) {
199 $man .= ".El\n.Pp\n";
207 if (m/^>(\w+)(\s+\d)?$/) {
208 my ($page, $sect) = ($1, $2 ? int($2) : 3);
209 ++$xref{$sect}->{$page};
212 if (s/^\s+(=?\w+):\s*/.It $1/) {
218 $man =~ s/\.Pp\n$//s;
219 $man .= ".Bl -tag -width 18n\n";
222 s/^\.It =([A-Z][A-Z_]+)$/.It Dv $1/gs;
225 } elsif ($inlist && m/^\S/) {
226 $man .= ".El\n.Pp\n";
228 } elsif ($inliteral && m/^\S/) {
231 } elsif ($inliteral) {
237 $man .= ".Bd -literal\n";
242 s/\s*=$func\b\s*/\n.Nm\n/gs;
243 s/\s*=$argnames\b\s*/\n.Fa $1\n/gs;
244 s/\s*=(struct \w+(?: \*)?)\b\s*/\n.Vt $1\n/gs;
245 s/\s*:([a-z_]+)\b\s*/\n.Va $1\n/gs;
246 s/\s*;([a-z_]+)\b\s*/\n.Dv $1\n/gs;
247 while (s/\s*=([a-z_]+)\b\s*/\n.Xr $1 3\n/s) {
250 s/\s*\"(?=\w)/\n.Do\n/gs;
251 s/\"(?!\w)\s*/\n.Dc\n/gs;
252 s/\s*=([A-Z][A-Z_]+)\b\s*(?![\.,:;])/\n.Dv $1\n/gs;
253 s/\s*=([A-Z][A-Z_]+)\b([\.,:;]+)\s*/\n.Dv $1 $2\n/gs;
254 s/\s*{([A-Z][a-z] .*?)}\s*/\n.$1\n/gs;
264 $man =~ s/(\n\.[A-Z][a-z] [\w ]+)\n([\.,:;-]\S*)\s*/$1 $2\n/gs;
265 $man =~ s/\s*$/\n/gm;
268 $man =~ s/\n\n\./\n\./gs;
271 $man = "No description available.";
274 $FUNCTIONS{$func} = {
282 'errors' => \@errors,
284 if ($source =~ m/^ \* NODOC\s*$/m) {
285 $FUNCTIONS{$func}->{'nodoc'} = 1;
287 if ($source !~ m/^ \* XSSO \d/m) {
288 $FUNCTIONS{$func}->{'openpam'} = 1;
290 expand_errors($FUNCTIONS{$func});
291 return $FUNCTIONS{$func};
294 sub expand_errors($);
295 sub expand_errors($) {
296 my $func = shift; # Ref to function hash
302 if (defined($func->{'recursed'})) {
303 warn("$func->{'name'}(): loop in error spec\n");
306 $func->{'recursed'} = 1;
308 foreach (@{$func->{'errors'}}) {
309 if (m/^(PAM_[A-Z_]+)$/) {
310 if (!defined($PAMERR{$1})) {
311 warn("$func->{'name'}(): unrecognized error: $1\n");
315 } elsif (m/^!(PAM_[A-Z_]+)$/) {
316 # treat negations separately
317 } elsif (m/^=([a-z_]+)$/) {
319 if (!defined($FUNCTIONS{$ref})) {
320 $fn = $func->{'source'};
321 $fn =~ s/$func->{'name'}/$ref/;
324 if (!defined($FUNCTIONS{$ref})) {
325 warn("$func->{'name'}(): reference to unknown $ref()\n");
328 foreach (@{$FUNCTIONS{$ref}->{'errors'}}) {
332 warn("$func->{'name'}(): invalid error specification: $_\n");
335 foreach (@{$func->{'errors'}}) {
336 if (m/^!(PAM_[A-Z_]+)$/) {
340 delete($func->{'recursed'});
341 $func->{'errors'} = [ sort(keys(%errors)) ];
344 sub dictionary_order($$) {
347 $a =~ s/[^[:alpha:]]//g;
348 $b =~ s/[^[:alpha:]]//g;
353 my $xref = shift; # References
357 foreach my $sect (sort(keys(%{$xref}))) {
358 foreach my $page (sort(dictionary_order keys(%{$xref->{$sect}}))) {
359 push(@refs, "$page $sect");
362 while ($_ = shift(@refs)) {
364 (@refs ? " ,\n" : "\n");
370 my $func = shift; # Ref to function hash
376 return if defined($func->{'nodoc'});
380 .Dt " . uc($func->{'name'}) . " 3
389 .In security/pam_appl.h
391 if ($func->{'name'} =~ m/_sm_/) {
392 $mdoc .= ".In security/pam_modules.h\n"
394 if ($func->{'name'} =~ m/openpam/) {
395 $mdoc .= ".In security/openpam.h\n"
397 $mdoc .= ".Ft \"$func->{'type'}\"
398 .Fn $func->{'name'} $func->{'args'}
402 if ($func->{'type'} eq "int") {
403 $mdoc .= ".Sh RETURN VALUES
406 function returns one of the following values:
409 my @errors = @{$func->{'errors'}};
410 warn("$func->{'name'}(): no error specification\n")
413 $mdoc .= ".It Bq Er $_\n$PAMERR{$_}.\n";
417 if ($func->{'type'} =~ m/\*$/) {
418 $mdoc .= ".Sh RETURN VALUES
427 $mdoc .= ".Sh SEE ALSO\n" . genxref($func->{'xref'});
428 $mdoc .= ".Sh STANDARDS\n";
429 if ($func->{'openpam'}) {
432 function is an OpenPAM extension.
436 .%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\"
441 $mdoc .= ".Sh AUTHORS
444 function and this manual page were developed for the
446 Project by ThinkSec AS and Network Associates Laboratories, the
447 Security Research Division of Network Associates, Inc.\\& under
448 DARPA/SPAWAR contract N66001-01-C-8035
450 as part of the DARPA CHATS research program.
453 $fn = "$func->{'name'}.3";
454 if (sysopen(FILE, $fn, O_RDWR|O_CREAT|O_TRUNC)) {
458 warn("$fn: open(): $!\n");
463 my $fn = shift; # File name
468 sysopen(FILE, $fn, O_RDONLY)
469 or die("$fn: open(): $!\n");
471 if (m/^\.Nm ((?:open)?pam_.*?)\s*$/) {
472 $func{'Nm'} = $func{'Nm'} || $1;
473 } elsif (m/^\.Ft (\S.*?)\s*$/) {
474 $func{'Ft'} = $func{'Ft'} || $1;
475 } elsif (m/^\.Fn (\S.*?)\s*$/) {
476 $func{'Fn'} = $func{'Fn'} || $1;
481 $FUNCTIONS{$func{'Nm'}} = \%func;
483 warn("No function found\n");
488 my $page = shift; # Which page to produce
495 sysopen(FILE, "$page.3", O_RDWR|O_CREAT|O_TRUNC)
496 or die("$page.3: $!\n");
499 print FILE "$COPYRIGHT
505 my @funcs = sort(keys(%FUNCTIONS));
506 while ($func = shift(@funcs)) {
507 print FILE ".Nm $FUNCTIONS{$func}->{'Nm'}";
512 print FILE ".Nd Pluggable Authentication Modules Library
516 if ($page eq 'pam') {
517 print FILE ".In security/pam_appl.h\n";
519 print FILE ".In security/openpam.h\n";
521 foreach $func (sort(keys(%FUNCTIONS))) {
522 print FILE ".Ft $FUNCTIONS{$func}->{'Ft'}\n";
523 print FILE ".Fn $FUNCTIONS{$func}->{'Fn'}\n";
526 if (m/^\.Xr (\S+)\s*(\d)\s*$/) {
527 ++$xref{int($2)}->{$1};
532 if ($page eq 'pam') {
533 print FILE ".Sh RETURN VALUES
534 The following return codes are defined by
535 .In security/pam_constants.h :
538 foreach (sort(keys(%PAMERR))) {
539 print FILE ".It Bq Er $_\n$PAMERR{$_}.\n";
543 print FILE ".Sh SEE ALSO
545 if ($page eq 'pam') {
546 ++$xref{3}->{'openpam'};
548 foreach $func (keys(%FUNCTIONS)) {
551 print FILE genxref(\%xref);
552 print FILE ".Sh STANDARDS
554 .%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\"
558 The OpenPAM library and this manual page were developed for the
560 Project by ThinkSec AS and Network Associates Laboratories, the
561 Security Research Division of Network Associates, Inc.\\& under
562 DARPA/SPAWAR contract N66001-01-C-8035
564 as part of the DARPA CHATS research program.
571 print(STDERR "usage: gendoc [-s] source [...]\n");
579 unless (@ARGV && getopts("op", \%opts));
580 setlocale(LC_ALL, "en_US.ISO8859-1");
581 $TODAY = strftime("%B %e, %Y", localtime(time()));
583 if ($opts{'o'} || $opts{'p'}) {
584 foreach my $fn (@ARGV) {
587 gensummary('openpam')
592 foreach my $fn (@ARGV) {
593 my $func = parse_source($fn);