1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
|
<!doctype linuxdoc system>
<!--
$Id: pam_modules.sgml,v 1.19 1997/04/05 06:49:14 morgan Exp morgan $
Copyright (c) Andrew G. Morgan 1996, 1997. All rights reserved.
** some sections, in this document, were contributed by other
** authors. They carry individual copyrights.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, and the entire permission notice in its entirety,
including the disclaimer of warranties.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote
products derived from this software without specific prior
written permission.
ALTERNATIVELY, this product may be distributed under the terms of the
GNU General Public License, in which case the provisions of the GNU
GPL are required INSTEAD OF the above restrictions. (This clause is
necessary due to a potential bad interaction between the GNU GPL and
the restrictions contained in a BSD-style copyright.)
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
-->
<article>
<title>The Linux-PAM Module Writers' Guide
<author>Andrew G. Morgan, <tt>morgan@transmeta.com</tt>
<date>DRAFT v0.59 1997/10/17
<abstract>
This manual documents what a programmer needs to know in order to
write a module that conforms to the <bf/Linux-PAM/ standard. It also
discusses some security issues from the point of view of the module
programmer.
</abstract>
<toc>
<sect>Introduction
<sect1> Synopsis
<p>
<tscreen>
<verb>
#include <security/pam_modules.h>
gcc -fPIC -c pam_module-name.c
ld -x --shared -o pam_module-name.so pam_module-name.o -lpam
</verb>
</tscreen>
<sect1> Description
<p>
<bf/Linux-PAM/ (Pluggable Authentication Modules for Linux) is a
library that enables the local system administrator to choose how
individual applications authenticate users. For an overview of the
<bf/Linux-PAM/ library see the <bf/Linux-PAM/ System Administrators'
Guide.
<p>
A <bf/Linux-PAM/ module is a single executable binary file that can be
loaded by the <bf/Linux-PAM/ interface library. This PAM library is
configured locally with a system file, <tt>/etc/pam.conf</tt>, to
authenticate a user request via the locally available authentication
modules. The modules themselves will usually be located in the
directory <tt>/usr/lib/security</tt> and take the form of dynamically
loadable object files (see dlopen(3)). Alternatively, the modules can
be statically linked into the <bf/Linux-PAM/ library; this is mostly to
allow <bf/Linux-PAM/ to be used on platforms without dynamic linking
available, but the two forms can be used together. It is the
<bf/Linux-PAM/ interface that is called by an application and it is
the responsibility of the library to locate, load and call the
appropriate functions in a <bf/Linux-PAM/-module.
<p>
Except for the immediate purpose of interacting with the user
(entering a password etc..) the module should never call the
application directly. This exception requires a "conversation
mechanism" which is documented below.
<sect>What can be expected by the module
<p>
Here we list the interface that the conventions that all
<bf/Linux-PAM/ modules must adhere to.
<sect1>Getting and setting <tt/PAM_ITEM/s and <em/data/
<p>
First, we cover what the module should expect from the <bf/Linux-PAM/
library and a <bf/Linux-PAM/ <em/aware/ application. Essesntially this
is the <tt/libpam.*/ library.
<sect2>
Setting data
<p>
Synopsis:
<tscreen>
<verb>
extern int pam_set_data(pam_handle_t *pamh
, const char *module_data_name
, void *data
, void (*cleanup)(pam_handle_t *pamh
, void *data
, int error_status)
);
</verb>
</tscreen>
<p>
The modules may be dynamically loadable objects. In general such files
should not contain <tt/static/ variables. This and the subsequent
function provide a mechanism for a module to associate some data with
the handle <tt/pamh/. Typically a module will call the
<tt/pam_set_data()/ function to register some data under a (hopefully)
unique <tt/module_data_name/. The data is available for use by other
modules too but <em/not/ by an application.
<p>
The function <tt/cleanup()/ is associated with the <tt/data/ and, if
non-<tt/NULL/, it is called when this data is over-written or
following a call to <tt/pam_end()/ (see the Linux-PAM Application
Developers' Guide).
<p>
The <tt/error_status/ argument is used to indicate to the module the
sort of action it is to take in cleaning this data item. As an
example, Kerberos creates a ticket file during the authentication
phase, this file might be associated with a data item. When
<tt/pam_end()/ is called by the module, the <tt/error_status/
carries the return value of the <tt/pam_authenticate()/ or other
<tt/libpam/ function as appropriate. Based on this value the Kerberos
module may choose to delete the ticket file (<em/authentication
failure/) or leave it in place.
<p>
(*This paragraph is currently under advisement with Sun*) The
<tt/error_status/ may have been logically OR'd with either of the
following two values:
<p>
<descrip>
<tag><tt/PAM_DATA_REPLACE/</tag>
When a data item is being replaced (through a second call to
<tt/pam_set_data()/) this mask is used is used. Otherwise, the call is
assumed to be from <tt/pam_end()/.
<tag><tt/PAM_DATA_SILENT/</tag>
Which indicates that the process would prefer to perform the
<tt/cleanup()/ quietly. That is, discourages logging/messages to the
user.
</descrip>
<sect2>
Getting data
<p>
Synopsis:
<tscreen>
<verb>
extern int pam_get_data(const pam_handle_t *pamh
, const char *module_data_name
, const void **data
);
</verb>
</tscreen>
<p>
This function together with the previous one provides a method of
associating module-specific data with the handle <tt/pamh/. A
successful call to <tt/pam_get_data/ will result in <tt/*data/
pointing to the data associated with the <tt/module_data_name/. Note,
this data is <em/not/ a copy and should be treated as <em/constant/
by the module.
<p>
Note, if there is an entry but it has the value <tt/NULL/, then this
call returns <tt/PAM_NO_MODULE_DATA/.
<sect2>
Setting items
<p>
Synopsis:
<tscreen>
<verb>
extern int pam_set_item(pam_handle_t *pamh
, int item_type
, const void *item
);
</verb>
</tscreen>
<p>
This function is used to (re)set the value of one of the
<tt/item_type/s. The reader is urged to read the entry for this
function in the <bf/Linux-PAM/ application developers' manual.
<p>
In addition to the <tt/item/s listed there, the module can set the
following two <tt/item_type/s:
<p>
<descrip>
<tag><tt/PAM_AUTHTOK/</tag>
The authentication token (password). This token should be ignored by
all module functions besides <tt/pam_sm_authenticate()/ and
<tt/pam_sm_chauthtok()/. In the former function it is used to pass the
most recent authentication token from one stacked module to
another. In the latter function the token is used for another
purpose. It contains the currently active authentication token.
<tag><tt/PAM_OLDAUTHTOK/</tag>
The old authentication token. This token should be ignored by all
module functions except <tt/pam_sm_chauthtok()/.
</descrip>
<p>
Both of these items are reset before returning to the application.
When resetting these items, the <bf/Linux-PAM/ library first writes
<tt/0/'s to the current tokens and then <tt/free()/'s the associated
memory.
<p>
The return values for this function are listed in the
<bf>Linux-PAM</bf> Application Developers' Guide.
<sect2>
Getting items
<p>
Synopsis:
<tscreen>
<verb>
extern int pam_get_item(const pam_handle_t *pamh
, int item_type
, const void **item
);
</verb>
</tscreen>
<p>
This function is used to obtain the value of the specified
<tt/item_type/. It is better documented in the <bf/Linux-PAM/
Application Developers' Guide. However, there are three things worth
stressing here:
<itemize>
<item>
Generally, if the module wishes to obtain the name of the user, it
should not use this function, but instead perform a call to
<tt/pam_get_user()/ (see section <ref id="pam-get-user"
name="below">).
<item>
The module is additionally privileged to read the authentication
tokens, <tt/PAM_AUTHTOK/ and <tt/PAM_OLDAUTHTOK/ (see the section
above on <tt/pam_set_data()/).
<item>
The module should <em/not/ <tt/free()/ or alter the data pointed to by
<tt/*item/ after a successful return from <tt/pam_get_item()/. This
pointer points directly at the data contained within the <tt/*pamh/
structure. Should a module require that a change is made to the this
<tt/ITEM/ it should make the appropriate call to <tt/pam_set_item()/.
</itemize>
<sect2>The <em/conversation/ mechanism
<p>
Following the call <tt>pam_get_item(pamh,PAM_CONV,&item)</tt>, the
pointer <tt/item/ points to a <em/conversation/-function that provides
limited but direct access to the application. The purpose of this
function is to allow the module to prompt the user for their password
and pass other information in a manner consistent with the
application. For example, an X-windows based program might pop up a
dialog box to report a login failure. Just as the application should
not be concerned with the method of authentication, so the module
should not dictate the manner in which input (output) is
obtained from (presented to) to the user.
<p>
The reader is strongly urged to read the more complete description of
the <tt/pam_conv/ structure, written from the perspective of the
application developer, in the <bf/Linux-PAM/ Application Developers'
Guide.
<p>
The <tt/pam_response/ structure returned after a call to the
<tt/pam_conv/ function must be <tt/free()/'d by the module. Since the
call to the conversation function originates from the module, it is
clear that either this <tt/pam_response/ structure could be either
statically or dynamically (using <tt/malloc()/ etc.) allocated within
the application. Repeated calls to the conversation function would
likely overwrite static memory, so it is required that for a
successful return from the conversation function the memory for the
response structure is dynamically allocated by the application with
one of the <tt/malloc()/ family of commands and <em/must/ be
<tt/free()/'d by the module.
<p>
If the <tt/pam_conv/ mechanism is used to enter authentication tokens,
the module should either pass the result to the <tt/pam_set_item()/
library function, or copy it itself. In such a case, once the token
has been stored (by one of these methods or another one), the memory
returned by the application should be overwritten with <tt/0/'s, and
then <tt/free()/'d.
<p>
The return values for this function are listed in the
<bf>Linux-PAM</bf> Application Developers' Guide.
<sect2>Getting the name of a user<label id="pam-get-user">
<p>
Synopsis:
<tscreen>
<verb>
extern int pam_get_user(pam_handle_t *pamh
, const char **user
, const char *prompt
);
</verb>
</tscreen>
<p>
This is a <bf/Linux-PAM/ library function that returns the
(prospective) name of the user. To determine the username it does the
following things, in this order:
<itemize>
<item> checks what <tt/pam_get_item(pamh, PAM_USER, ... );/ would have
returned. If this is not <tt/NULL/ this is what it returns. Otherwise,
<item> obtains a username from the application via the <tt/pam_conv/
mechanism, it prompts the user with the first non-<tt/NULL/ string in
the following list:
<itemize>
<item> The <tt/prompt/ argument passed to the function
<item> What is returned by <tt/pam_get_item(pamh,PAM_USER_PROMPT, ... );/
<item> The default prompt: ``Please enter username: ''
</itemize>
</itemize>
<p>
By whatever means the username is obtained, a pointer to it is
returned as the contents of <tt/*user/. Note, this memory should
<em/not/ be <tt/free()/'d by the module. Instead, it will be liberated
on the next call to <tt/pam_get_user()/, or by <tt/pam_end()/ when the
application ends its interaction with <bf/Linux-PAM/.
<p>
Also, in addition, it should be noted that this function sets the
<tt/PAM_USER/ item that is associated with the <tt/pam_[gs]et_item()/
function.
<sect2>Setting a Linux-PAM environment variable
<p>
Synopsis:
<tscreen>
<verb>
extern int pam_putenv(pam_handle_t *pamh, const char *name_value);
</verb>
</tscreen>
<p>
<bf/Linux-PAM/ (0.54+) comes equipped with a series of functions for
maintaining a set of <em/environment/ variables. The environment is
initialized by the call to <tt/pam_start()/ and is <bf/erased/ with a
call to <tt/pam_end()/. This <em/environment/ is associated with the
<tt/pam_handle_t/ pointer returned by the former call.
<p>
The default environment is all but empty. It contains a single
<tt/NULL/ pointer, which is always required to terminate the
variable-list. The <tt/pam_putenv()/ function can be used to add a
new environment variable, replace an existing one, or delete an old
one.
<p>
<itemize>
<item>Adding/replacing a variable<newline>
To add or overwrite a <bf/Linux-PAM/ environment variable the value of
the argument <tt/name_value/, should be of the following form:
<tscreen>
<verb>
name_value="VARIABLE=VALUE OF VARIABLE"
</verb>
</tscreen>
Here, <tt/VARIABLE/ is the environment variable's name and what
follows the `<tt/=/' is its (new) value. (Note, that <tt/"VARIABLE="/
is a valid value for <tt/name_value/, indicating that the variable is
set to <tt/""/.)
<item> Deleting a variable<newline>
To delete a <bf/Linux-PAM/ environment variable the value of
the argument <tt/name_value/, should be of the following form:
<tscreen>
<verb>
name_value="VARIABLE"
</verb>
</tscreen>
Here, <tt/VARIABLE/ is the environment variable's name and the absence
of an `<tt/=/' indicates that the variable should be removed.
</itemize>
<p>
In all cases <tt/PAM_SUCCESS/ indicates success.
<sect2>Getting a Linux-PAM environment variable
<p>
Synopsis:
<tscreen>
<verb>
extern const char *pam_getenv(pam_handle_t *pamh, const char *name);
</verb>
</tscreen>
<p>
This function can be used to return the value of the given
variable. If the returned value is <tt/NULL/, the variable is not
known.
<sect2>Listing the Linux-PAM environment
<p>
Synopsis:
<tscreen>
<verb>
extern char * const *pam_getenvlist(pam_handle_t *pamh);
</verb>
</tscreen>
<p>
This function returns a pointer to the entire <bf/Linux-PAM/
environment array. At first sight the <em/type/ of the returned data
may appear a little confusing. It is basically a <em/read-only/ array
of character pointers, that lists the <tt/NULL/ terminated list of
environment variables set so far.
<p>
Although, this is not a concern for the module programmer, we mention
here that an application should be careful to copy this entire array
before executing <tt/pam_end()/ otherwise all the variable information
will be lost. (There are functions in <tt/libpam_misc/ for this
purpose: <tt/pam_misc_copy_env()/ and <tt/pam_misc_drop_env()/.)
<sect1>Other functions provided by <tt/libpam/
<sect2>Understanding errors
<p>
<itemize>
<item>
<tt>extern const char *pam_strerror(pam_handle_t *pamh, int errnum);</tt>
<p>
This function returns some text describing the <bf/Linux-PAM/ error
associated with the argument <tt/errnum/. If the error is not
recognized <tt/``Unknown Linux-PAM error''/ is returned.
</itemize>
<sect2>Planning for delays
<p>
<itemize>
<item>
<tt>extern int pam_fail_delay(pam_handle_t *pamh, unsigned int
micro_sec)</tt>
<p>
This function is offered by <bf/Linux-PAM/ to facilitate time delays
following a failed call to <tt/pam_authenticate()/ and before control
is returned to the application. When using this function the module
programmer should check if it is available with,
<tscreen>
<verb>
#ifdef HAVE_PAM_FAIL_DELAY
....
#endif /* HAVE_PAM_FAIL_DELAY */
</verb>
</tscreen>
<p>
Generally, an application requests that a user is authenticated by
<bf/Linux-PAM/ through a call to <tt/pam_authenticate()/ or
<tt/pam_chauthtok()/. These functions calls each of the <em/stacked/
authentication modules listed in the <tt>/etc/pam.conf</tt> file. As
directed by this file, one of more of the modules may fail causing the
<tt/pam_...()/ call to return an error. It is desirable for there to
also be a pause before the application continues. The principal reason
for such a delay is security: a delay acts to discourage <em/brute
force/ dictionary attacks primarily, but also helps hinder
<em/timed/ (covert channel) attacks.
<p>
The <tt/pam_fail_delay()/ function provides the mechanism by which an
application or module can suggest a minimum delay (of <tt/micro_sec/
<em/micro-seconds/). <bf/Linux-PAM/ keeps a record of the longest time
requested with this function. Should <tt/pam_authenticate()/ fail,
the failing return to the application is delayed by an amount of time
randomly distributed (by up to 25%) about this longest value.
<p>
Independent of success, the delay time is reset to its zero default
value when <bf/Linux-PAM/ returns control to the application.
</itemize>
<sect>What is expected of a module
<p>
The module must supply a sub-set of the six functions listed
below. Together they define the function of a <bf/Linux-PAM
module/. Module developers are strongly urged to read the comments on
security that follow this list.
<sect1> Overview
<p>
The six module functions are grouped into four independent management
groups. These groups are as follows: <em/authentication/,
<em/account/, <em/session/ and <em/password/. To be properly defined,
a module must define all functions within at least one of these
groups. A single module may contain the necessary functions for
<em/all/ four groups.
<sect2> Functional independence
<p>
The independence of the four groups of service a module can offer
means that the module should allow for the possibility that any one of
these four services may legitimately be called in any order. Thus, the
module writer should consider the appropriateness of performing a
service without the prior success of some other part of the module.
<p>
As an informative example, consider the possibility that an
application applies to change a user's authentication token, without
having first requested that <bf/Linux-PAM/ authenticate the user. In
some cases this may be deemed appropriate: when <tt/root/ wants to
change the authentication token of some lesser user. In other cases it
may not be appropriate: when <tt/joe/ maliciously wants to reset
<tt/alice/'s password; or when anyone other than the user themself
wishes to reset their <em/KERBEROS/ authentication token. A policy for
this action should be defined by any reasonable authentication scheme,
the module writer should consider this when implementing a given
module.
<sect2> Minimizing administration problems
<p>
To avoid system administration problems and the poor construction of a
<tt>/etc/pam.conf</tt> file, the module developer may define all
six of the following functions. For those functions that would not be
called, the module should return <tt/PAM_SERVICE_ERR/ and write an
appropriate message to the system log. When this action is deemed
inappropriate, the function would simply return <tt/PAM_IGNORE/.
<sect2> Arguments supplied to the module
<p>
The <tt/flags/ argument of each of the following functions can be
logically OR'd with <tt/PAM_SILENT/, which is used to inform the
module to not pass any <em/text/ (errors or warnings) to the
application.
<p>
The <tt/argc/ and <tt/argv/ arguments are taken from the line
appropriate to this module---that is, with the <em/service_name/
matching that of the application---in the configuration file (see the
<bf/Linux-PAM/ System Administrators' Guide). Together these two
parameters provide the number of arguments and an array of pointers to
the individual argument tokens. This will be familiar to C programmers
as the ubiquitous method of passing command arguments to the function
<tt/main()/. Note, however, that the first argument (<tt/argv[0]/) is
a true argument and <bf/not/ the name of the module.
<sect1> Authentication management
<p>
To be correctly initialized, <tt/PAM_SM_AUTH/ must be <tt/#define/'d
prior to including <tt><security/pam_modules.h></tt>. This will
ensure that the prototypes for static modules are properly declared.
<p>
<itemize>
<item>
<tt>PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
int argc, const char **argv);</tt>
<p>
This function performs the task of authenticating the user.
<p>
The <tt/flags/ argument can be a logically OR'd with <tt/PAM_SILENT/
and optionally take the following value:
<p><descrip>
<tag><tt/PAM_DISALLOW_NULL_AUTHTOK/</tag>
return <tt/PAM_AUTH_ERR/ if the database of authentication
tokens for this authentication mechanism has a <tt/NULL/ entry for the
user. Without this flag, such a <tt/NULL/ token will lead to a success
without the user being prompted.
</descrip>
<p>
Besides <tt/PAM_SUCCESS/ return values that can be sent by this
function are one of the following:
<descrip>
<tag><tt/PAM_AUTH_ERR/</tag>
The user was not authenticated
<tag><tt/PAM_CRED_INSUFFICIENT/</tag>
For some reason the application does not have sufficient
credentials to authenticate the user.
<tag><tt/PAM_AUTHINFO_UNAVAIL/</tag>
The modules were not able to access the authentication
information. This might be due to a network or hardware failure etc.
<tag><tt/PAM_USER_UNKNOWN/</tag>
The supplied username is not known to the authentication
service
<tag><tt/PAM_MAXTRIES/</tag>
One or more of the authentication modules has reached its
limit of tries authenticating the user. Do not try again.
</descrip>
<item>
<tt>PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int
argc, const char **argv);</tt>
<p>
This function performs the task of altering the credentials of the
user with respect to the corresponding authorization
scheme. Generally, an authentication module may have access to more
information about a user than their authentication token. This
function is used to append such information to the application. It
should only be called <em/after/ the user has been authenticated.
<p>
Permitted flags, one of which, may be logically OR'd with
<tt/PAM_SILENT/ are,
<p><descrip>
<tag><tt/PAM_ESTABLISH_CRED/</tag>
Set the credentials for the authentication service,
<tag><tt/PAM_DELETE_CRED/</tag>
Delete the credentials associated with the authentication service,
<tag><tt/PAM_REINITIALIZE_CRED/</tag>
Reinitialize the user credentials, and
<tag><tt/PAM_REFRESH_CRED/</tag>
Extend the lifetime of the user credentials.
</descrip>
<p>
Besides <tt/PAM_SUCCESS/, the module may return one of the following
errors:
<p><descrip>
<tag><tt/PAM_CRED_UNAVAIL/</tag>
This module cannot retrieve the user's credentials.
<tag><tt/PAM_CRED_EXPIRED/</tag>
The user's credentials have expired.
<tag><tt/PAM_USER_UNKNOWN/</tag>
The user is not known to this authentication module.
<tag><tt/PAM_CRED_ERR/</tag>
This module was unable to set the credentials of the user.
</descrip>
</itemize>
<sect1> Account management
<p>
To be correctly initialized, <tt/PAM_SM_ACCOUNT/ must be
<tt/#define/'d prior to including <tt><security/pam_modules.h></tt>.
This will ensure that the prototype for a static module is properly
declared.
<p>
<itemize>
<item>
<tt>PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int
argc, const char **argv);</tt>
<p>
This function performs the task of establishing whether the user is
permitted to gain access at this time. It should be understood that
the user has previously been validated by an authentication
module. This function checks for other things. Such things might be:
the time of day or the date, the terminal line, remote
hostname, etc. .
<p>
This function may also determine things like the expiration on
passwords, and respond that the user change it before continuing.
<p>
Valid flags, which may be logically OR'd with <tt/PAM_SILENT/, are the
same as those applicable to the <tt/flags/ argument of
<tt/pam_sm_authenticate/.
<p>
This function may return one of the following errors,
<descrip>
<tag><tt/PAM_ACCT_EXPIRED/</tag>
The user is no longer permitted access to the system.
<tag><tt/PAM_AUTH_ERR/</tag>
There was an authentication error.
<tag><tt/PAM_AUTHTOKEN_REQD/</tag>
The user's authentication token has expired. Before calling
this function again the application will arrange for a new one to be
given. This will likely result in a call to <tt/pam_sm_chauthtok()/.
<tag><tt/PAM_USER_UNKNOWN/</tag>
The user is not known to the module's account management
component.
</descrip>
</itemize>
<sect1> Session management
<p>
To be correctly initialized, <tt/PAM_SM_SESSION/ must be
<tt/#define/'d prior to including
<tt><security/pam_modules.h></tt>. This will ensure that the
prototypes for static modules are properly declared.
<p>
The following two functions are defined to handle the
initialization/termination of a session. For example, at the beginning
of a session the module may wish to log a message with the system
regarding the user. Similarly, at the end of the session the module
would inform the system that the user's session has ended.
<p>
It should be possible for sessions to be opened by one application and
closed by another. This either requires that the module uses only
information obtained from <tt/pam_get_item()/, or that information
regarding the session is stored in some way by the operating system
(in a file for example).
<p>
<itemize>
<item>
<tt>PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int
argc, const char **argv);</tt>
<p>
This function is called to commence a session. The only valid, but
optional, flag is <tt/PAM_SILENT/.
<p>
As a return value, <tt/PAM_SUCCESS/ signals success and
<tt/PAM_SESSION_ERR/ failure.
<item>
<tt>PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int
argc, const char **argv);</tt>
<p>
This function is called to terminate a session. The only valid, but
optional, flag is <tt/PAM_SILENT/.
<p>
As a return value, <tt/PAM_SUCCESS/ signals success and
<tt/PAM_SESSION_ERR/ failure.
</itemize>
<sect1> Password management
<p>
To be correctly initialized, <tt/PAM_SM_PASSWORD/ must be
<tt/#define/'d prior to including <tt><security/pam_modules.h></tt>.
This will ensure that the prototype for a static module is properly
declared.
<p>
<itemize>
<item>
<tt>PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int
argc, const char **argv);</tt>
<p>
This function is used to (re-)set the authentication token of the
user. A valid flag, which may be logically OR'd with <tt/PAM_SILENT/,
can be built from the following list,
<descrip>
<tag><tt/PAM_CHANGE_EXPIRED_AUTHTOK/</tag>
This argument indicates to the module that the users
authentication token (password) should only be changed if it has
expired. This flag is optional and <em/must/ be combined with one of
the following two flags. Note, however, the following two options are
<em/mutually exclusive/.
<tag><tt/PAM_PRELIM_CHECK/</tag>
This indicates that the modules are being probed as to their
ready status for altering the user's authentication token. If the
module requires access to another system over some network it should
attempt to verify it can connect to this system on receiving this
flag. If a module cannot establish it is ready to update the user's
authentication token it should return <tt/PAM_TRY_AGAIN/, this
information will be passed back to the application.
<tag><tt/PAM_UPDATE_AUTHTOK/</tag>
This informs the module that this is the call it should change
the authorization tokens. If the flag is logically OR'd with
<tt/PAM_CHANGE_EXPIRED_AUTHTOK/, the token is only changed if it has
actually expired.
</descrip>
<p>
Note, the <bf/Linux-PAM/ library calls this function twice in
succession. The first time with <tt/PAM_PRELIM_CHECK/ and then, if the
module does not return <tt/PAM_TRY_AGAIN/, subsequently with
<tt/PAM_UPDATE_AUTHTOK/. It is only on the second call that the
authorization token is (possibly) changed.
<p>
<tt/PAM_SUCCESS/ is the only successful return value, valid
error-returns are:
<descrip>
<tag><tt/PAM_AUTHTOK_ERR/</tag>
The module was unable to obtain the new authentication token.
<tag><tt/PAM_AUTHTOK_RECOVERY_ERR/</tag>
The module was unable to obtain the old authentication token.
<tag><tt/PAM_AUTHTOK_LOCK_BUSY/</tag>
Cannot change the authentication token since it is currently
locked.
<tag><tt/PAM_AUTHTOK_DISABLE_AGING/</tag>
Authentication token aging has been disabled.
<tag><tt/PAM_PERM_DENIED/</tag>
Permission denied.
<tag><tt/PAM_TRY_AGAIN/</tag>
Preliminary check was unsuccessful. Signals an immediate return
to the application is desired.
<tag><tt/PAM_USER_UNKNOWN/</tag>
The user is not known to the authentication token changing
service.
</descrip>
</itemize>
<sect>Generic optional arguments
<p>
Here we list the generic arguments that all modules can expect to
be passed. They are not mandatory, and their absence should be
accepted without comment by the module.
<p>
<descrip>
<tag><tt/debug/</tag>
Use the <tt/syslog(3)/ call to log debugging information to the system
log files.
<tag><tt/no_warn/</tag>
Instruct module to not give warning messages to the application.
<tag><tt/use_first_pass/</tag>
The module should not prompt the user for a password. Instead, it
should obtain the previously typed password (by a call to
<tt/pam_get_item()/ for the <tt/PAM_AUTHTOK/ item), and use that. If
that doesn't work, then the user will not be authenticated. (This
option is intended for <tt/auth/ and <tt/passwd/ modules only).
<tag><tt/try_first_pass/</tag>
The module should attempt authentication with the previously typed
password (by a call to <tt/pam_get_item()/ for the <tt/PAM_AUTHTOK/
item). If that doesn't work, then the user is prompted for a
password. (This option is intended for <tt/auth/ modules only).
<tag><tt/use_mapped_pass/</tag>
<bf/WARNING:/ coding this functionality may cause the module writer to
break <em/local/ encryption laws. For example, in the U.S. there are
restrictions on the export computer code that is capable of strong
encryption. It has not been established whether this option is
affected by this law, but one might reasonably assume that it does
until told otherwise. For this reason, this option is not supported
by any of the modules distributed with <bf/Linux-PAM/.
The intended function of this argument, however, is that the module
should take the existing authentication token from a previously
invoked module and use it as a key to retrieve the authentication
token for this module. For example, the module might create a strong
hash of the <tt/PAM_AUTHTOK/ item (established by a previously
executed module). Then, with logical-exclusive-or, use the result as a
<em/key/ to safely store/retrieve the authentication token for this
module in/from a local file <em/etc/. .
</descrip>
<sect>Programming notes
<p>
Here we collect some pointers for the module writer to bear in mind
when writing/developing a <bf/Linux-PAM/ compatible module.
<sect1>Security issues for module creation
<sect2>Sufficient resources
<p>
Care should be taken to ensure that the proper execution of a module
is not compromised by a lack of system resources. If a module is
unable to open sufficient files to perform its task, it should fail
gracefully, or request additional resources. Specifically, the
quantities manipulated by the <tt/setrlimit(2)/ family of commands
should be taken into consideration.
<sect2>Who's who?
<p>
Generally, the module may wish to establish the identity of the user
requesting a service. This may not be the same as the username
returned by <tt/pam_get_user()/. Indeed, that is only going to be the
name of the user under whose identity the service will be given. This
is not necessarily the user that requests the service.
<p>
In other words, user X runs a program that is setuid-Y, it grants the
user to have the permissions of Z. A specific example of this sort of
service request is the <em/su/ program: user <tt/joe/ executes
<em/su/ to become the user <em/jane/. In this situation X=<tt/joe/,
Y=<tt/root/ and Z=<tt/jane/. Clearly, it is important that the module
does not confuse these different users and grant an inappropriate
level of privilege.
<p>
The following is the convention to be adhered to when juggling
user-identities.
<p>
<itemize>
<item>X, the identity of the user invoking the service request.
This is the user identifier; returned by the function <tt/getuid(2)/.
<item>Y, the privileged identity of the application used to grant the
requested service. This is the <em/effective/ user identifier;
returned by the function <tt/geteuid(2)/.
<item>Z, the user under whose identity the service will be granted.
This is the username returned by <tt/pam_get_user(2)/ and also stored
in the <bf/Linux-PAM/ item, <tt/PAM_USER/.
<item><bf/Linux-PAM/ has a place for an additional user identity that
a module may care to make use of. This is the <tt/PAM_RUSER/ item.
Generally, network sensitive modules/applications may wish to set/read
this item to establish the identity of the user requesting a service
from a remote location.
</itemize>
<p>
Note, if a module wishes to modify the identity of either the <tt/uid/
or <tt/euid/ of the running process, it should take care to restore
the original values prior to returning control to the <bf/Linux-PAM/
library.
<sect2>Using the conversation function
<p>
Prior to calling the conversation function, the module should reset
the contents of the pointer that will return the applications
response. This is a good idea since the application may fail to fill
the pointer and the module should be in a position to notice!
<p>
The module should be prepared for a failure from the conversation. The
generic error would be <tt/PAM_CONV_ERR/, but anything other than
<tt/PAM_SUCCESS/ should be treated as indicating failure.
<sect2>Authentication tokens
<p>
To ensure that the authentication tokens are not left lying around the
items, <tt/PAM_AUTHTOK/ and <tt/PAM_OLDAUTHTOK/, are not available to
the application: they are defined in
<tt><security/pam_modules.h></tt>. This is ostensibly for
security reasons, but a maliciously programmed application will always
have access to all memory of the process, so it is only superficially
enforced. As a general rule the module should overwrite
authentication tokens as soon as they are no longer needed.
Especially before <tt/free()/'ing them. The <bf/Linux-PAM/ library is
required to do this when either of these authentication token items
are (re)set.
<p>
Not to dwell too little on this concern; should the module store the
authentication tokens either as (automatic) function variables or
using <tt/pam_[gs]et_data()/ the associated memory should be
over-written explicitly before it is released. In the case of the
latter storage mechanism, the associated <tt/cleanup()/ function
should explicitly overwrite the <tt/*data/ before <tt/free()/'ing it:
for example,
<tscreen>
<verb>
/*
* An example cleanup() function for releasing memory that was used to
* store a password.
*/
int cleanup(pam_handle_t *pamh, void *data, int error_status)
{
char *xx;
if ((xx = data)) {
while (*xx)
*xx++ = '\0';
free(data);
}
return PAM_SUCCESS;
}
</verb>
</tscreen>
<sect1>Use of <tt/syslog(3)/
<p>
Only rarely should error information be directed to the user. Usually,
this is to be limited to ``<em/sorry you cannot login now/'' type
messages. Information concerning errors in the configuration file,
<tt>/etc/pam.conf</tt>, or due to some system failure encountered by
the module, should be written to <tt/syslog(3)/ with
<em/facility-type/ <tt/LOG_AUTHPRIV/.
<p>
With a few exceptions, the level of logging is, at the discretion of
the module developer. Here is the recommended usage of different
logging levels:
<p>
<itemize>
<item>
As a general rule, errors encountered by a module should be logged at
the <tt/LOG_ERR/ level. However, information regarding an unrecognized
argument, passed to a module from an entry in the
<tt>/etc/pam.conf</tt> file, is <bf/required/ to be logged at the
<tt/LOG_ERR/ level.
<item>
Debugging information, as activated by the <tt/debug/ argument to the
module in <tt>/etc/pam.conf</tt>, should be logged at the
<tt/LOG_DEBUG/ level.
<item>
If a module discovers that its personal configuration file or some
system file it uses for information is corrupted or somehow unusable,
it should indicate this by logging messages at level, <tt/LOG_ALERT/.
<item>
Shortages of system resources, such as a failure to manipulate a file
or <tt/malloc()/ failures should be logged at level <tt/LOG_CRIT/.
<item>
Authentication failures, associated with an incorrectly typed password
should be logged at level, <tt/LOG_NOTICE/.
</itemize>
<sect1> Modules that require system libraries
<p>
Writing a module is much like writing an application. You have to
provide the "conventional hooks" for it to work correctly, like
<tt>pam_sm_authenticate()</tt> etc., which would correspond to the
<tt/main()/ function in a normal function.
<p>
Typically, the author may want to link against some standard system
libraries. As when one compiles a normal program, this can be done for
modules too: you simply append the <tt>-l</tt><em>XXX</em> arguments
for the desired libraries when you create the shared module object. To
make sure a module is linked to the <tt>lib<em>whatever</em>.so</tt>
library when it is <tt>dlopen()</tt>ed, try:
<tscreen>
<verb>
% gcc -shared -Xlinker -x -o pam_module.so pam_module.o -lwhatever
</verb>
</tscreen>
<sect1> Added requirements for <em/statically/ loaded modules.
<!--
Copyright (C) Michael K. Johnson 1996.
Last modified: AGM 1996/5/31.
-->
<p>
Modules may be statically linked into libpam. This should be true of
all the modules distributed with the basic <bf/Linux-PAM/
distribution. To be statically linked, a module needs to export
information about the functions it contains in a manner that does not
clash with other modules.
The extra code necessary to build a static module should be delimited
with <tt/#ifdef PAM_STATIC/ and <tt/#endif/. The static code should do
the following:
<itemize>
<item> Define a single structure, <tt/struct pam_module/, called
<tt>_pam_<it>modname</it>_modstruct</tt>, where
<tt><it>modname</it></tt> is the name of the module <bf/as used in the
filesystem/ but without the leading directory name (generally
<tt>/usr/lib/security/</tt> or the suffix (generally <tt/.so/).
</itemize>
<p>
As a simple example, consider the following module code which defines
a module that can be compiled to be <em/static/ or <em/dynamic/:
<p>
<tscreen>
<verb>
#include <stdio.h> /* for NULL define */
#define PAM_SM_PASSWORD /* the only pam_sm_... function declared */
#include <security/pam_modules.h>
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
return PAM_SUCCESS;
}
#ifdef PAM_STATIC /* for the case that this module is static */
struct pam_module _pam_modname_modstruct = { /* static module data */
"pam_modname",
NULL,
NULL,
NULL,
NULL,
NULL,
pam_sm_chauthtok,
};
#endif /* end PAM_STATIC */
</verb>
</tscreen>
<p>
To be linked with <em/libpam/, staticly-linked modules must be built
from within the <tt>Linux-PAM-X.YY/modules/</tt> subdirectory of the
<bf/Linux-PAM/ source directory as part of a normal build of the
<bf/Linux-PAM/ system.
The <em/Makefile/, for the module in question, must execute the
<tt/register_static/ shell script that is located in the
<tt>Linux-PAM-X.YY/modules/</tt> subdirectory. This is to ensure that
the module is properly registered with <em/libpam/.
The <bf/two/ manditory arguments to <tt/register_static/ are the
title, and the pathname of the object file containing the module's
code. The pathname is specified relative to the
<tt>Linux-PAM-X.YY/modules</tt> directory. The pathname may be an
empty string---this is for the case that a single object file needs to
register more than one <tt/struct pam_module/. In such a case, exactly
one call to <tt/register_static/ must indicate the object file.
<p>
Here is an example; a line in the <em/Makefile/ might look like this:
<tscreen>
<verb>
register:
ifdef STATIC
(cd ..; ./register_static pam_modname pam_modname/pam_modname.o)
endif
</verb>
</tscreen>
For some further examples, see the <tt>modules</tt> subdirectory of
the current <bf/Linux-PAM/ distribution.
<p>
<sect>An example module file
<p>
<em>
perhaps this should point to a place in the file structure!?
</em>
<sect>Files
<p><descrip>
<tag><tt>/usr/lib/libpam.so.*</tt></tag>
the shared library providing applications with access to
<bf/Linux-PAM/.
<tag><tt>/etc/pam.conf</tt></tag>
the <bf/Linux-PAM/ configuration file.
<tag><tt>/usr/lib/security/pam_*.so</tt></tag>
the primary location for <bf/Linux-PAM/ dynamically loadable object
files; the modules.
</descrip>
<sect>See also
<p><itemize>
<item>The <bf/Linux-PAM/ System Administrators' Guide.
<item>The <bf/Linux-PAM/ Application Writers' Guide.
<item>
V. Samar and R. Schemers (SunSoft), ``UNIFIED LOGIN WITH PLUGGABLE
AUTHENTICATION MODULES'', Open Software Foundation Request For
Comments 86.0, October 1995.
</itemize>
<sect>Notes
<p>
I intend to put development comments here... like ``at the moment
this isn't actually supported''. At release time what ever is in
this section will be placed in the Bugs section below! :)
<p>
<itemize>
<item>
Perhaps we should keep a registry of data-names as used by
<tt/pam_[gs]et_data()/ so there are no unintentional problems due to
conflicts?
<item>
<tt/pam_strerror()/ should be internationalized....
<item>
There has been some debate about whether <tt/initgroups()/ should be
in an application or in a module. It was settled by Sun who stated
that initgroups is an action of the <em/application/. The modules are
permitted to add additional groups, however.
<item>
Refinements/futher suggestions to <tt/syslog(3)/ usage by modules are
needed.
</itemize>
<sect>Author/acknowledgments
<p>
This document was written by Andrew G. Morgan
(<tt/morgan@transmeta.com/) with many contributions from
<!-- insert credits here -->
<!--
an sgml list of people to credit for their contributions to Linux-PAM
-->
<!--
an sgml list of people to credit for their contributions to Linux-PAM
$Id: CREDITS,v 1.4 1997/04/05 06:47:26 morgan Exp morgan $
-->
Peter Allgeyer,
Tim Baverstock,
Craig S. Bell,
Derrick J. Brashear,
Ben Buxton,
Oliver Crow,
Chris Dent,
Marc Ewing,
Cristian Gafton,
Eric Hester,
Roger Hu,
Eric Jacksch,
Michael K. Johnson,
David Kinchlea,
Nicolai Langfeldt,
Elliot Lee,
Al Longyear,
Ingo Luetkebohle,
Marek Michalkiewicz,
Aleph One,
Martin Pool,
Sean Reifschneider,
Erik Troan,
Theodore Ts'o,
Jeff Uphoff,
Myles Uyema,
Savochkin Andrey Vladimirovich,
Ronald Wahl,
David Wood,
John Wilmes,
Joseph S. D. Yao
and
Alex O. Yuriev.
<p>
Thanks are also due to Sun Microsystems, especially to Vipin Samar and
Charlie Lai for their advice. At an early stage in the development of
<bf/Linux-PAM/, Sun graciously made the documentation for their
implementation of PAM available. This act greatly accelerated the
development of <bf/Linux-PAM/.
<sect>Bugs/omissions
<p>
Few PAM modules currently exist. Few PAM-aware applications exist.
This document is hopelessly unfinished. Only a partial list of people is
credited for all the good work they have done.
<sect>Copyright information for this document
<p>
Copyright (c) Andrew G. Morgan 1996, 1997. All rights reserved.
<newline>
Email: <tt><morgan@transmeta.com></tt>
<p>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
<p>
<itemize>
<item>
1. Redistributions of source code must retain the above copyright
notice, and the entire permission notice in its entirety,
including the disclaimer of warranties.
<item>
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
<item>
3. The name of the author may not be used to endorse or promote
products derived from this software without specific prior
written permission.
</itemize>
<p>
<bf/Alternatively/, this product may be distributed under the terms of
the GNU General Public License (GPL), in which case the provisions of
the GNU GPL are required <bf/instead of/ the above restrictions.
(This clause is necessary due to a potential bad interaction between
the GNU GPL and the restrictions contained in a BSD-style copyright.)
<p>
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
<p>
<tt>$Id: pam_modules.sgml,v 1.19 1997/04/05 06:49:14 morgan Exp morgan $</tt>
</article>
|