Merge from vendor branch HEIMDAL:
[dragonfly.git] / crypto / heimdal-0.6.3 / doc / heimdal.info-2
1 This is Info file heimdal.info, produced by Makeinfo version 1.68 from
2 the input file heimdal.texi.
3
4 INFO-DIR-SECTION Heimdal
5 START-INFO-DIR-ENTRY
6 * Heimdal: (heimdal).           The Kerberos 5 distribution from KTH
7 END-INFO-DIR-ENTRY
8
9 \1f
10 File: heimdal.info,  Node: kaserver,  Prev: Converting a version 4 database,  Up: Kerberos 4 issues
11
12 kaserver
13 ========
14
15 kaserver emulation
16 ------------------
17
18 The Heimdal kdc can emulate a kaserver. The kaserver is a Kerberos 4
19 server with pre-authentication using Rx as the on-wire protocol. The kdc
20 contains a minimalistic Rx implementation.
21
22 There are three parts of the kaserver; KAA (Authentication), KAT (Ticket
23 Granting), and KAM (Maintenance). The KAA interface and KAT interface
24 both passes over DES encrypted data-blobs (just like the
25 Kerberos-protocol) and thus do not need any other protection.  The KAM
26 interface uses `rxkad' (Kerberos authentication layer for Rx) for
27 security and data protection, and is used for example for changing
28 passwords.  This part is not implemented in the kdc.
29
30 Another difference between the ka-protocol and the Kerberos 4 protocol
31 is that the pass-phrase is salted with the cellname in the `string to
32 key' function in the ka-protocol, while in the Kerberos 4 protocol there
33 is no salting of the password at all. To make sure AFS-compatible keys
34 are added to each principals when they are created or their password are
35 changed, `afs3-salt' should be added to `[kadmin]default_keys'.
36
37 Transarc AFS Windows client
38 ---------------------------
39
40 The Transarc Windows client uses Kerberos 4 to obtain tokens, and thus
41 does not need a kaserver. The Windows client assumes that the Kerberos
42 server is on the same machine as the AFS-database server. If you do not
43 like to do that you can add a small program that runs on the database
44 servers that forward all kerberos requests to the real kerberos server.
45 A program that does this is `krb-forward'
46 (`ftp://ftp.stacken.kth.se/pub/projekts/krb-forward').
47
48 \1f
49 File: heimdal.info,  Node: Windows 2000 compatability,  Next: Programming with Kerberos,  Prev: Kerberos 4 issues,  Up: Top
50
51 Windows 2000 compatability
52 **************************
53
54 Windows 2000 (formerly known as Windows NT 5) from Microsoft implements
55 Kerberos 5.  Their implementation, however, has some quirks,
56 peculiarities, and bugs.  This chapter is a short summary of the things
57 that we have found out while trying to test Heimdal against Windows
58 2000.  Another big problem with the Kerberos implementation in Windows
59 2000 is that the available documentation is more focused on getting
60 things to work rather than how they work and not that useful in figuring
61 out how things really work.
62
63 This information should apply to Heimdal 0.3a and Windows 2000
64 Professional.  It's of course subject all the time and mostly consists
65 of our not so inspired guesses.  Hopefully it's still somewhat useful.
66
67 * Menu:
68
69 * Configuring Windows 2000 to use a Heimdal KDC::
70 * Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC::
71 * Create account mappings::
72 * Encryption types::
73 * Authorization data::
74 * Quirks of Windows 2000 KDC::
75 * Useful links when reading about the Windows 2000::
76
77 \1f
78 File: heimdal.info,  Node: Configuring Windows 2000 to use a Heimdal KDC,  Next: Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC,  Prev: Windows 2000 compatability,  Up: Windows 2000 compatability
79
80 Configuring Windows 2000 to use a Heimdal KDC
81 =============================================
82
83 You need the command line program called `ksetup.exe' which is available
84 in the file `SUPPORT/TOOLS/SUPPORT.CAB' on the Windows 2000 Professional
85 CD-ROM. This program is used to configure the Kerberos settings on a
86 Workstation.
87
88 `Ksetup' store the domain information under the registry key:
89 `HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\LSA\Kerberos\Domains'.
90
91 Use the kadmin program in Heimdal to create a host principal in the
92 Kerberos realm.
93
94      unix% kadmin
95      kadmin> ank -pw password host/datan.my.domain
96
97 You must configure the Workstation as a member of a workgroup, as
98 opposed to a member in an NT domain, and specify the KDC server of the
99 realm as follows:
100      C:> ksetup /setdomain MY.REALM
101      C:> ksetup /addkdc MY.REALM kdc.my.domain
102
103 Set the machine password, i.e. create the local keytab:
104      C:> ksetup /setmachpassword password
105
106 The workstation must now be rebooted.
107
108 A mapping between local NT users and Kerberos principals must be
109 specified, you have two choices:
110
111      C:> ksetup /mapuser user@MY.REALM nt_user
112
113 This will map a user to a specific principal, this allows you to have
114 other usernames in the realm than in your NT user database. (Don't ask
115 me why on earth you would want that...)
116
117 You can also say:
118      C:> ksetup /mapuser * *
119 The Windows machine will now map any user to the corresponding
120 principal, for example `nisse' to the principal `nisse@MY.REALM'.
121 (This is most likely what you want.)
122
123 \1f
124 File: heimdal.info,  Node: Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC,  Next: Create account mappings,  Prev: Configuring Windows 2000 to use a Heimdal KDC,  Up: Windows 2000 compatability
125
126 Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC
127 ===============================================================
128
129 See also the Step-by-Step guide from Microsoft, referenced below.
130
131 Install Windows 2000, and create a new controller (Active Directory
132 Server) for the domain.
133
134 By default the trust will be non-transitive. This means that only users
135 directly from the trusted domain may authenticate. This can be changed
136 to transitive by using the `netdom.exe' tool.
137
138 You need to tell Windows 2000 on what hosts to find the KDCs for the
139 non-Windows realm with `ksetup', see *Note Configuring Windows 2000 to
140 use a Heimdal KDC::.
141
142 This need to be done on all computers that want enable cross-realm
143 login with `Mapped Names'.
144
145 Then you need to add the inter-realm keys on the Windows kdc. Start the
146 Domain Tree Management tool. (Found in Programs, Administrative tools,
147 Active Directory Domains and Trusts).
148
149 Right click on Properties of your domain, select the Trust tab.  Press
150 Add on the appropriate trust windows and enter domain name and
151 password. When prompted if this is a non-Windows Kerberos realm, press
152 OK.
153
154 Do not forget to add trusts in both directions.
155
156 You also need to add the inter-realm keys to the Heimdal KDC. There are
157 some tweaks that you need to do to `krb5.conf' beforehand.
158
159      [libdefaults]
160         default_etypes = des-cbc-crc
161         default_etypes_des = des-cbc-crc
162
163 since otherwise checksum types that are not understood by Windows 2000
164 will be generated (*Note Quirks of Windows 2000 KDC::.).
165
166 Another issue is salting.  Since Windows 2000 does not seem to
167 understand Kerberos 4 salted hashes you might need to turn off anything
168 similar to the following if you have it, at least while adding the
169 principals that are going to share keys with Windows 2000.
170
171         [kadmin]default_keys = v5 v4
172
173 You must also set:
174
175 Once that is also done, you can add the required inter-realm keys:
176
177      kadmin add krbtgt/NT.REALM.EXAMPLE.COM@EXAMPLE.COM
178      kadmin add krbtgt/REALM.EXAMPLE.COM@NT.EXAMPLE.COM
179
180 Use the same passwords for both keys.
181
182 Do not forget to reboot before trying the new realm-trust (after running
183 `ksetup'). It looks like it might work, but packets are never sent to
184 the non-Windows KDC.
185
186 \1f
187 File: heimdal.info,  Node: Create account mappings,  Next: Encryption types,  Prev: Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC,  Up: Windows 2000 compatability
188
189 Create account mappings
190 =======================
191
192 Start the `Active Directory Users and Computers' tool. Select the View
193 menu, that is in the left corner just below the real menu (or press
194 Alt-V), and select Advanced Features. Right click on the user that you
195 are going to do a name mapping for and choose Name mapping.
196
197 Click on the Kerberos Names tab and add a new principal from the
198 non-Windows domain.
199
200 \1f
201 File: heimdal.info,  Node: Encryption types,  Next: Authorization data,  Prev: Create account mappings,  Up: Windows 2000 compatability
202
203 Encryption types
204 ================
205
206 Windows 2000 supports both the standard DES encryptions (des-cbc-crc and
207 des-cbc-md5) and its own proprietary encryption that is based on MD4 and
208 rc4 that is documented in and is supposed to be described in
209 `draft-brezak-win2k-krb-rc4-hmac-03.txt'.  New users will get both MD4
210 and DES keys.  Users that are converted from a NT4 database, will only
211 have MD4 passwords and will need a password change to get a DES key.
212
213 Heimdal implements both of these encryption types, but since DES is the
214 standard and the hmac-code is somewhat newer, it is likely to work
215 better.
216
217 \1f
218 File: heimdal.info,  Node: Authorization data,  Next: Quirks of Windows 2000 KDC,  Prev: Encryption types,  Up: Windows 2000 compatability
219
220 Authorization data
221 ==================
222
223 The Windows 2000 KDC also adds extra authorization data in tickets.  It
224 is at this point unclear what triggers it to do this.  The format of
225 this data is only available under a "secret" license from Microsoft,
226 which prohibits you implementing it.
227
228 A simple way of getting hold of the data to be able to understand it
229 better is described here.
230
231   1. Find the client example on using the SSPI in the SDK documentation.
232
233   2. Change "AuthSamp" in the source code to lowercase.
234
235   3. Build the program.
236
237   4. Add the "authsamp" principal with a known password to the
238      database.  Make sure it has a DES key.
239
240   5. Run `ktutil add' to add the key for that principal to a keytab.
241
242   6. Run `appl/test/nt_gss_server -p 2000 -s authsamp --dump-auth=file'
243      where file is an appropriate file.
244
245   7. It should authenticate and dump for you the authorization data in
246      the file.
247
248   8. The tool `lib/asn1/asn1_print' is somewhat useful for analyzing
249      the data.
250
251 \1f
252 File: heimdal.info,  Node: Quirks of Windows 2000 KDC,  Next: Useful links when reading about the Windows 2000,  Prev: Authorization data,  Up: Windows 2000 compatability
253
254 Quirks of Windows 2000 KDC
255 ==========================
256
257 There are some issues with salts and Windows 2000.  Using an empty salt,
258 which is the only one that Kerberos 4 supported and is therefore known
259 as a Kerberos 4 compatible salt does not work, as far as we can tell
260 from out experiments and users reports.  Therefore, you have to make
261 sure you keep around keys with all the different types of salts that are
262 required.
263
264 Microsoft seems also to have forgotten to implement the checksum
265 algorithms `rsa-md4-des' and `rsa-md5-des'. This can make Name mapping
266 (*note Create account mappings::.) fail if a `des-cbc-md5' key is used.
267 To make the KDC return only `des-cbc-crc' you must delete the
268 `des-cbc-md5' key from the kdc using the `kadmin del_enctype' command.
269
270      kadmin del_enctype lha des-cbc-md5
271
272 You should also add the following entries to the `krb5.conf' file:
273
274      [libdefaults]
275         default_etypes = des-cbc-crc
276         default_etypes_des = des-cbc-crc
277
278 These configuration options will make sure that no checksums of the
279 unsupported types are generated.
280
281 \1f
282 File: heimdal.info,  Node: Useful links when reading about the Windows 2000,  Prev: Quirks of Windows 2000 KDC,  Up: Windows 2000 compatability
283
284 Useful links when reading about the Windows 2000
285 ================================================
286
287 See also our paper presented at the 2001 usenix Annual Technical
288 Conference, available in the proceedings or at
289 `http://www.usenix.org/publications/library/proceedings/usenix01/freenix01/westerlund.html'.
290
291 There are lots of text about Kerberos on Microsoft's web site, here is a
292 short list of the interesting documents that we have managed to find.
293
294    * Step-by-Step Guide to Kerberos 5 (krb5 1.0) Interoperability -
295
296
297
298
299
300
301
302
303
304
305
306      `http://www.microsoft.com/windows2000/library/planning/security/kerbsteps.asp'
307      Kerberos GSS-API (in Windows-ize SSPI), Windows as a client in a
308      non-Windows KDC realm, adding unix clients to a Windows 2000 KDC,
309      and adding cross-realm trust (*Note Inter-Realm keys (trust)
310      between Windows 2000 and a Heimdal KDC::.).
311
312    * Windows 2000 Kerberos Authentication -
313
314
315
316
317
318
319      `http://www.microsoft.com/TechNet/win2000/win2ksrv/technote/kerberos.asp'
320      White paper that describes how Kerberos is used in Windows 2000.
321
322    * Overview of kerberos -
323      `http://support.microsoft.com/support/kb/articles/Q248/7/58.ASP'
324      Links to useful other links.
325
326    * Klist for windows -
327
328
329
330      `http://msdn.microsoft.com/library/periodic/period00/security0500.htm'
331      Describes where to get a klist for Windows 2000.
332
333    * Event logging for kerberos -
334      `http://support.microsoft.com/support/kb/articles/Q262/1/77.ASP'.
335      Basicly it say that you can add a registry key
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355      `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\LogLevel'
356      with value DWORD equal to 1, and then you'll get logging in the
357      Event Logger.
358
359    * Access to the active directory through LDAP
360      `http://msdn.microsoft.com/library/techart/kerberossamp.htm'
361
362 Other useful programs include these:
363
364    * pwdump2 `http://www.webspan.net/~tas/pwdump2/'
365
366 \1f
367 File: heimdal.info,  Node: Programming with Kerberos,  Next: Migration,  Prev: Windows 2000 compatability,  Up: Top
368
369 Programming with Kerberos
370 *************************
371
372 First you need to know how the Kerberos model works, go read the
373 introduction text (*note What is Kerberos?::.).
374
375 * Menu:
376
377 * Kerberos 5 API Overview::
378 * Walkthru a sample Kerberos 5 client::
379 * Validating a password in a server application::
380
381 \1f
382 File: heimdal.info,  Node: Kerberos 5 API Overview,  Next: Walkthru a sample Kerberos 5 client,  Prev: Programming with Kerberos,  Up: Programming with Kerberos
383
384 Kerberos 5 API Overview
385 =======================
386
387 Most functions are documenteded in manual pages.  This overview only
388 tries to point to where to look for a specific function.
389
390 Kerberos context
391 ----------------
392
393 A kerberos context (`krb5_context') holds all per thread state. All
394 global variables that are context specific are stored in this struture,
395 including default encryption types, credential-cache (ticket file), and
396 default realms.
397
398 See the manual pages for `krb5_context(3)' and `krb5_init_context(3)'.
399
400 Kerberos authenication context
401 ------------------------------
402
403 Kerberos authentication context (`krb5_auth_context') holds all context
404 related to an authenticated connection, in a similar way to the
405 kerberos context that holds the context for the thread or process.
406
407 The `krb5_auth_context' is used by various functions that are directly
408 related to authentication between the server/client. Example of data
409 that this structure contains are various flags, addresses of client and
410 server, port numbers, keyblocks (and subkeys), sequence numbers, replay
411 cache, and checksum types.
412
413 See the manual page for `krb5_auth_context(3)'.
414
415 Keytab management
416 -----------------
417
418 A keytab is a storage for locally stored keys. Heimdal includes keytab
419 support for Kerberos 5 keytabs, Kerberos 4 srvtab, AFS-KeyFile's, and
420 for storing keys in memory.
421
422 See also manual page for `krb5_keytab(3)'
423
424 \1f
425 File: heimdal.info,  Node: Walkthru a sample Kerberos 5 client,  Next: Validating a password in a server application,  Prev: Kerberos 5 API Overview,  Up: Programming with Kerberos
426
427 Walkthru a sample Kerberos 5 client
428 ===================================
429
430 This example contains parts of a sample TCP Kerberos 5 clients, if you
431 want a real working client, please look in `appl/test' directory in the
432 Heimdal distribution.
433
434 All Kerberos error-codes that are returned from kerberos functions in
435 this program are passed to `krb5_err', that will print a descriptive
436 text of the error code and exit. Graphical programs can convert
437 error-code to a humal readable error-string with the
438 `krb5_get_err_text(3)' function.
439
440 Note that you should not use any Kerberos function before
441 `krb5_init_context()' have completed successfully. That is the reson
442 `err()' is used when `krb5_init_context()' fails.
443
444 First the client needs to call `krb5_init_context' to initialize the
445 Kerberos 5 library. This is only needed once per thread in the program.
446 If the function returns a non-zero value it indicates that either the
447 Kerberos implemtation is failing or its disabled on this host.
448
449      #include <krb5.h>
450      
451      int
452      main(int argc, char **argv)
453      {
454              krb5_context context;
455      
456              if (krb5_context(&context))
457                      errx (1, "krb5_context");
458
459 Now the client wants to connect to the host at the other end. The
460 preferred way of doing this is using `getaddrinfo(3)' (for operating
461 system that have this function implemented), since getaddrinfo is
462 neutral to the address type and can use any protocol that is available.
463
464              struct addrinfo *ai, *a;
465              struct addrinfo hints;
466              int error;
467      
468              memset (&hints, 0, sizeof(hints));
469              hints.ai_socktype = SOCK_STREAM;
470              hints.ai_protocol = IPPROTO_TCP;
471      
472              error = getaddrinfo (hostname, "pop3", &hints, &ai);
473              if (error)
474                      errx (1, "%s: %s", hostname, gai_strerror(error));
475      
476              for (a = ai; a != NULL; a = a->ai_next) {
477                      int s;
478      
479                      s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
480                      if (s < 0)
481                              continue;
482                      if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
483                              warn ("connect(%s)", hostname);
484                                  close (s);
485                                  continue;
486                      }
487                      freeaddrinfo (ai);
488                      ai = NULL;
489              }
490              if (ai) {
491                          freeaddrinfo (ai);
492                          errx ("failed to contact %s", hostname);
493              }
494
495 Before authenticating, an authentication context needs to be created.
496 This context keeps all information for one (to be) authenticated
497 connection (see `krb5_auth_context(3)').
498
499              status = krb5_auth_con_init (context, &auth_context);
500              if (status)
501                      krb5_err (context, 1, status, "krb5_auth_con_init");
502
503 For setting the address in the authentication there is a help function
504 `krb5_auth_con_setaddrs_from_fd' that does everthing that is needed
505 when given a connected file descriptor to the socket.
506
507              status = krb5_auth_con_setaddrs_from_fd (context,
508                                                       auth_context,
509                                                       &sock);
510              if (status)
511                      krb5_err (context, 1, status,
512                                "krb5_auth_con_setaddrs_from_fd");
513
514 The next step is to build a server principal for the service we want to
515 connect to. (See also `krb5_sname_to_principal(3)'.)
516
517              status = krb5_sname_to_principal (context,
518                                                hostname,
519                                                service,
520                                                KRB5_NT_SRV_HST,
521                                                &server);
522              if (status)
523                      krb5_err (context, 1, status, "krb5_sname_to_principal");
524
525 The client principal is not passed to `krb5_sendauth(3)' function, this
526 causes the `krb5_sendauth' function to try to figure it out itself.
527
528 The server program is using the function `krb5_recvauth(3)' to receive
529 the Kerberos 5 authenticator.
530
531 In this case, mutual authenication will be tried. That means that the
532 server will authenticate to the client. Using mutual authenication is
533 good since it enables the user to verify that they are talking to the
534 right server (a server that knows the key).
535
536 If you are using a non-blocking socket you will need to do all work of
537 `krb5_sendauth' yourself. Basically you need to send over the
538 authenticator from `krb5_mk_req(3)' and, in case of mutual
539 authentication, verifying the result from the server with
540 `krb5_rd_rep(3)'.
541
542              status = krb5_sendauth (context,
543                                      &auth_context,
544                                      &sock,
545                                      VERSION,
546                                      NULL,
547                                      server,
548                                      AP_OPTS_MUTUAL_REQUIRED,
549                                      NULL,
550                                      NULL,
551                                      NULL,
552                                      NULL,
553                                      NULL,
554                                      NULL);
555              if (status)
556                      krb5_err (context, 1, status, "krb5_sendauth");
557
558 Once authentication has been performed, it is time to send some data.
559 First we create a krb5_data structure, then we sign it with
560 `krb5_mk_safe(3)' using the `auth_context' that contains the
561 session-key that was exchanged in the
562 `krb5_sendauth(3)'/`krb5_recvauth(3)' authentication sequence.
563
564              data.data   = "hej";
565              data.length = 3;
566      
567              krb5_data_zero (&packet);
568      
569              status = krb5_mk_safe (context,
570                                     auth_context,
571                                     &data,
572                                     &packet,
573                                     NULL);
574              if (status)
575                      krb5_err (context, 1, status, "krb5_mk_safe");
576
577 And send it over the network.
578
579              len = packet.length;
580              net_len = htonl(len);
581      
582              if (krb5_net_write (context, &sock, &net_len, 4) != 4)
583                      err (1, "krb5_net_write");
584              if (krb5_net_write (context, &sock, packet.data, len) != len)
585                      err (1, "krb5_net_write");
586
587 To send encrypted (and signed) data `krb5_mk_priv(3)' should be used
588 instead. `krb5_mk_priv(3)' works the same way as `krb5_mk_safe(3)',
589 with the exception that it encrypts the data in addition to signing it.
590
591              data.data   = "hemligt";
592              data.length = 7;
593      
594              krb5_data_free (&packet);
595      
596              status = krb5_mk_priv (context,
597                                     auth_context,
598                                     &data,
599                                     &packet,
600                                     NULL);
601              if (status)
602                      krb5_err (context, 1, status, "krb5_mk_priv");
603
604 And send it over the network.
605
606              len = packet.length;
607              net_len = htonl(len);
608      
609              if (krb5_net_write (context, &sock, &net_len, 4) != 4)
610                      err (1, "krb5_net_write");
611              if (krb5_net_write (context, &sock, packet.data, len) != len)
612                      err (1, "krb5_net_write");
613
614 The server is using `krb5_rd_safe(3)' and `krb5_rd_priv(3)' to verify
615 the signature and decrypt the packet.
616
617 \1f
618 File: heimdal.info,  Node: Validating a password in a server application,  Prev: Walkthru a sample Kerberos 5 client,  Up: Programming with Kerberos
619
620 Validating a password in an application
621 =======================================
622
623 See the manual page for `krb5_verify_user(3)'.
624
625 \1f
626 File: heimdal.info,  Node: Migration,  Next: Acknowledgments,  Prev: Programming with Kerberos,  Up: Top
627
628 Migration
629 *********
630
631 General issues
632 ==============
633
634 When migrating from a Kerberos 4 KDC.
635
636 Order in what to do things:
637 ===========================
638
639    * Convert the database, check all principals that hprop complains
640      about.
641
642      `hprop -n --source=<NNN>| hpropd -n'
643
644      Replace <NNN> with whatever source you have, like krb4-db or
645      krb4-dump.
646
647    * Run a Kerberos 5 slave for a while.
648
649    * Figure out if it does everything you want it to.
650
651      Make sure that all things that you use works for you.
652
653    * Let a small number of controlled users use Kerberos 5 tools.
654
655      Find a sample population of your users and check what programs
656      they use, you can also check the kdc-log to check what ticket are
657      checked out.
658
659    * Burn the bridge and change the master.
660
661    * Let all users use the Kerberos 5 tools by default.
662
663    * Turn off services that do not need Kerberos 4 authentication.
664
665      Things that might be hard to get away is old programs with support
666      for Kerberos 4. Example applications are old Eudora installations
667      using KPOP, and Zephyr. Eudora can use the Kerberos 4 kerberos in
668      the Heimdal kdc.
669
670 \1f
671 File: heimdal.info,  Node: Acknowledgments,  Prev: Migration,  Up: Top
672
673 Acknowledgments
674 ***************
675
676 Eric Young wrote "libdes".
677
678 The University of California at Berkeley initially wrote `telnet', and
679 `telnetd'.  The authentication and encryption code of `telnet' and
680 `telnetd' was added by David Borman (then of Cray Research, Inc).  The
681 encryption code was removed when this was exported and then added back
682 by Juha Eskelinen, <esc@magic.fi>.
683
684 The `popper' was also a Berkeley program initially.
685
686 Some of the functions in `libroken' also come from Berkeley by way of
687 NetBSD/FreeBSD.
688
689 `editline' was written by Simmule Turner and Rich Salz.
690
691 The `getifaddrs' implementation for Linux was written by Hideaki
692 YOSHIFUJI for the Usagi project.
693
694 Bugfixes, documentation, encouragement, and code has been contributed
695 by:
696 Derrick J Brashear
697      <shadow@dementia.org>
698
699 Ken Hornstein
700      <kenh@cmf.nrl.navy.mil>
701
702 Johan Ihrén
703      <johani@pdc.kth.se>
704
705 Love Hörnquist-Åstrand
706      <lha@stacken.kth.se>
707
708 Magnus Ahltorp
709      <map@stacken.kth.se>
710
711 Mark Eichin
712      <eichin@cygnus.com>
713
714 Marc Horowitz
715      <marc@cygnus.com>
716
717 Luke Howard
718      <lukeh@PADL.COM>
719
720 Brandon S. Allbery KF8NH
721      <allbery@kf8nh.apk.net>
722
723 Jun-ichiro itojun Hagino
724      <itojun@kame.net>
725
726 Daniel Kouril
727      <kouril@informatics.muni.cz>
728
729 Åke Sandgren
730      <ake@cs.umu.se>
731
732 Michal Vocu
733      <michal@karlin.mff.cuni.cz>
734
735 Miroslav Ruda
736      <ruda@ics.muni.cz>
737
738 Brian A May
739      <bmay@snoopy.apana.org.au>
740
741 Chaskiel M Grundman
742      <cg2v@andrew.cmu.edu>
743
744 Richard Nyberg
745      <rnyberg@it.su.se>
746
747 Frank van der Linden
748      <fvdl@netbsd.org>
749
750 Cizzi Storm
751      <cizzi@it.su.se>
752
753 and we hope that those not mentioned here will forgive us.
754 All bugs were introduced by ourselves.
755
756