--- /dev/null
+* xref:index.adoc[Concepts]
+** General
+*** xref:aaa.adoc[AAA]
+** Modules
+*** LDAP
+**** xref:modules/ldap/authentication.adoc[Authentication]
--- /dev/null
+= AAA
+
+== Authorization, Authentication, and Accounting request handling
+
+There are a lot of questions about misconfigured FreeRADIUS servers
+because of misunderstanding of FreeRADIUS operations. This document
+explains how the server operates.
+
+Normally there are two steps in processing an authentication request
+coming from a NAS in FreeRADIUS: authorization and authentication.
+If we use FreeRADIUS as a proxy to re-send the request to another
+RADIUS server there will be additional steps.
+
+=== Authorization
+
+Authorization is the process of finding and returning information
+about what the user is allowed to do. For example, finding out what
+kind of authentication methods they are allowed to run, and what VLAN
+the user should be placed into.
+
+Authorization modules generally "get data" from somewhere,
+e.g. `ldap`, `sql`, `files`, etc.
+
+The authentication method is usually determined when the server gets
+the users credentials from a database. Once the credentials are
+available, the server can authenticate the user.
+
+=== Authentication
+
+Authentication is simply a process of comparing user’s credentials in
+request with the "known good" credentials retrieved from a
+database. Authentication usually deals with password
+encryption. The modules `pap`, `chap`, `mschap`, etc. do authentication.
+
+Some modules do both authentication and limited authorization. For
+example, the `mschap` module authenticates MS-CHAP credentials, but it
+may also be used as an authorization module, which verifies that
+request contains `MS-CHAP` related attribute. If so, the module
+instructs the server to use `mschap` for authentication, too
+
+These dual modules are usually related to protocol-specific
+attributes, such as the `pap` module for the `User-Password`
+attribute, `chap` for `CHAP-Password`, `mschap` for `MS-CHAP-*`, etc.
+
+=== Request Processing
+
+When the server processes requests, it manages four
+xref:unlang:list.adoc[attribute lists]:
+
+`request`:: attributes taken from the received packet
+
+`reply`:: attributes which will be sent in the reply
+
+`control`:: attributes used to control how the server operates. These are never sent in a packet
+
+`session-state`:: attributes which are saved and restroed across multiple request / reply exchanges.
+
+All of these lists are available to all modules. All of these
+lists are available in xref:unlang:index.adoc[Unlang].
+
--- /dev/null
+= Concepts
+
+This section documents concerning the protocols and modules used by the
+FreeRADIUS server.
+
+It intended to provide more theoretical information about particular subjects
+than would be appropriate to include inline in module configurations or as
+sidebars in howto guides.
--- /dev/null
+== Authenticating Users with LDAP
+
+Please be aware the FreeRADIUS is an AAA server, and LDAP
+is a _database_. This separation of roles means that FreeRADIUS
+supports multiple kinds of authentication protocols such as `PAP`,
+`CHAP`, `MS-CHAP`, etc. An LDAP database supports only one
+authentication method: "bind as user". This authentication method is
+compatible only with PAP.
+
+Our recommendation is to use LDAP as a database. FreeRADIUS should
+read the "known good" password from LDAP, and then use that
+information to authenticate the user. It is almost always wrong to
+use the LDAP "bind as user" method for authenticating users.
+
+The only caveat to the above recommendation is Active Directory. For
+"security" reasons, Active Directory will not return the "known good"
+password to FreeRADIUS over a standard LDAP query. Therefore when
+Active Directory is used, the choices are:
+
+PAP::
+Use "bind as user"
+
+MS-CHAP::
+Use xref:raddb:mods-available/ntlm_auth.adoc[`ntlm`] or xref:raddb:mods-available/winbind.adoc[`winbind`].
+
+Due to the limitations of Active Directory, There are unfortunately no
+other possible choices.
+
+== LDAP Security Recommendations
+
+The credentials (username *and* password) for FreeRADIUS to use to
+connect to your LDAP server(s) should be secure. We make the
+following recommendations for LDAP "best practices" security.
+
+* Create a dedicated account for use by FreeRADIUS
+
+* Ensure that this account does not have administrator access
+
+* Ensure that this account is read-only, and has no write permissions
+
+* Start by using 'simple authentication' instead of
+ https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer[SASL].
+ The SASL protocol should be attempted only after 'simple
+ authentication' has been verified to work.
+
+* Use TLS for connecting between FreeRADIUS and the LDAP server. See
+ the `tls` sub-section of the default `ldap` module for instructions
+
+* When storing RADIUS user profiles (quotas, `Simultaneous-Use` flags,
+ access time restrictions, etc) in LDAP, the LDAP schema
+ `doc/schemas/ldap/openldap/freeradius-radius.schema` must first be imported
+ into the LDAP server.
+
+== Authentication method compatibility
+
+The LDAP module is compatible a few different kinds of authentication
+methods. Note that we say _compatible_, and not _supports_. LDAP
+servers are databases, and do not support authentication protocols
+such as CHAP, MS-CHAP, or EAP.
+
+PAP::
+The user supplies a `User-Password` (plaintext or EAP-TTLS/PAP)
++
+FreeRADIUS reads the "known good" password from LDAP, and compares
+that to what the user entered.
+
+Bind as user::
+The user supplies a `User-Password` (plaintext or EAP-TTLS/PAP)
++
+FreeRADIUS uses that password to "bind as the user" to LDAP, using the
+supplied `User-Name` and `User-Password. If the bind is successfull,
+the user is authenticated. Otherwise, authentication fails.
+
+CHAP::
+The user supplies a `CHAP` password attribute.
++
+FreeRADIUS reads the "known good" password from LDAP in cleartext, and
+compares that to what the user entered.
+
+MS-CHAP::
+The user supplies a `MS-CHAP` password attribute. Either as
+MS-CHAPv2, or as PEAP/MSCHAPv2, or as EAP-TTLS/MS-CHAPv2.
++
+FreeRADIUS reads the "known good" password from LDAP in cleartext, or
+as an NT hash, and compares that to what the user entered.
+
+All of above authentication methods other than "bind as user" require
+that FreeRADIUS obtain the `userPassword` field from LDAP. If that
+field is not returned to FreeRADIUS, then normal authentication is
+impossible. Either FreeRADIUS has to be configured to use "bind as
+user" for authentication, or the LDAP database has to be updated to
+return the `userPassword` field to FreeRADIUS. This change usually
+involves giving the FreeRADIUS "read-only" user permission to read the
+`userPassword` field.
+
+Again, the best method is to test authentication is with the
+xref:howto:modules/ldap/ldapsearch/index.adoc[ldapsearch] tool.
+These tests *must* be run prior to configuring FreeRADIUS. We strongly
+recommend having the LDAP database return the `userPassword` field to
+FreeRADIUS, so that FreeRADIUS can authenticate the user.
+
+We also strongly recommend that the passwords be stored in LDAP as
+cleartext. Otherwise, the only authentication methods that will work
+are PAP and EAP-TTLS/PAP. The next section explains these issues in
+more detail.
+
+== Password Storage Methods
+
+If the `userPassword` field is returned from LDAP to FreeRADIUS, that
+information can be stored in a number of different formats:
+
+* the value can be cleartext
+* the value can be prepended with a string enclosed by braces, such as with `{crypt}` or `{ssha3}`.
+* the value can be have a suffix of `::`, in which case the password is generally a https://en.wikipedia.org/wiki/Base64[base64] encoded version of the real password
+
+TIP: Base64 values can be decoded via the command: `printf "%s"
+"VALUE" | base64 -d`
+
+FreeRADIUS is capable of understanding and parsing all of the above
+formats. There is sufficient information in the password values to
+determine what format it is in (base64, binary, or text), and what
+password "encryption" mechanism has been used (crypt, MD5, SHA, SSHA2,
+SHA3, etc). All that is necessary is that the
+xref:raddb:mods-available/ldap.adoc[ldap module] be configured to map
+the `userPassword` LDAP field to the `&control.Password.With-Header`
+attribute in FreeRADIUS. FreeRADIUS will then "do the right thing" to
+authenticate the user.
+
+This mapping is done in the default module configuration. There are
+no additional changes required for FreeRADIUS to correctly read and
+decode the `userPassword` field from LDAP. Please see the
+xref:raddb:mods-available/pap.adoc[pap module] for a full list of
+supported password "encryption" formats.
+
+== Additional Considerations
+
+There are some major caveats with the above authentication methods.
+The first is that we *strongly recommend* against using "bind as
+user". This process is slow, and causes unnecessary churn in the
+connections used to contact the LDAP server. Further, the "bind as
+user" process works _only_ when a `User-Password attribute exists in
+the request. If any other authentication type is used in the request,
+then the "bind as user" _will not work_. There is no amount of
+"fixing" things or configuration changes which will make it work.
+
+The second caveat is that the `CHAP` authentication type works _only_
+when a "clear text" password is stored in the LDAP database. The
+`CHAP` calclulations are designed around having access to the "clear
+text" password. It is impossible to use any "encrypted" or "hashed"
+passwords with `CHAP`.
+
+The third caveat is that the `MS-CHAP` authentication type works
+_only_ when a "clear text" password or "NT hashed" passwords which are
+stored in the LDAP database. The `MS-CHAP` calculations are designed
+around having access to "known good" passwords in those formats. It
+is impossible to use any other kind of "encrypted" or "hashed"
+passwords with `MS-CHAP`.
+
+The final caveat is that when the LDAP database contains "encrypted"
+or "hashed" passwords, the _only_ authentication type which is
+compatible with those passwords is PAP. i.e. when the `User-Password`
+is supplied to FreeRADIUS.
+
+For recommendations on password storage methods in LDAP, please see
+the LDAP
+https://openldap.org/doc/admin24/security.html#Password%20Storage[password
+storage] page. Please note that the recommendations there are made
+for LDAP security, and pay no attention to the caveats described
+above. When both RADIUS and LDAP are used together, then the
+requirements of _both_ systems must be met in order for them to work
+together. In many cases, a naive approach to LDAP security will
+prevent RADIUS from working.
+
+The issue of a database storing passwords in clear-text has to be
+balanced against the users sending clear-text passwords in
+authentication protocols. While those passwords are protected by TLS
+(EAP-TTLS) or by RADIUS (in it's own "encryption" mechanism), it is
+generally better to use a stronger authentication method than just
+PAP.
+
+In the end, there is no perfect solution to security requirements.
+The choice may be either to give up on using a particular
+authentication method, or to relax the security requirements on LDAP
+and on password storage. The final decision as to which choice is
+best can only be made by a local administrator.
+
+== Integrating Novell eDirectory with FreeRADIUS
+
+You can integrate Novell eDirectoryTM 8.7.1 or later with FreeRADIUS
+1.0.2 onwards to allow wireless authentication for eDirectory users. By
+integrating eDirectory with FreeRADIUS, you can do the following:
+
+* Use universal password for RADIUS authentication. Universal password
+provides single login and authentication for eDirectory users.
+Therefore, the users need not have a separate password for RADIUS and
+eDirectory authentication.
+* Enforce eDirectory account policies for users. The existing eDirectory
+policies on the user accounts can still be applied even after
+integrating with RADIUS. Also, you can make use of the intruder lockout
+facility of eDirectory by logging the failed logins into eDirectory.
+
+For configuration information please refer to the Novell documentation
+https://www.netiq.com/documentation/edir_radius/
--- /dev/null
+* xref:index.adoc[Developers]
+** xref:bugs.adoc[Bugs]
+** xref:coding-methods.adoc[Coding Methods]
+** xref:coverage.adoc[Code Coverage]
+** xref:profile.adoc[Profiling]
+** xref:contributing.adoc[Contributing]
+** xref:release-method.adoc[Release Method]
--- /dev/null
+= Bugs
+
+== Introduction
+
+The FreeRADIUS web site is at https://freeradius.org/, and most
+information referenced in this document can be found there.
+
+This document is primarily for non-developers of the FreeRADIUS
+server. If you are able to patch the code to work correctly, then
+we invite you to join the development list to discuss it. If
+you’re the type who know little about how to code, then this is
+the place for you!
+
+== You found a bug
+
+Where the server terminates ungracefully due to a bus error,
+segmentation violation, or other memory error, you should create a new
+issue in the issue tracker https://bugs.freeradius.org/, including
+information from the debugging sections below.
+
+For any other issues, you should first discuss them on the
+https://freeradius.org/support/[FreeRADIUS users list], to
+see if anyone can reproduce them. Often there’s a simple explanation of
+why the server behaves as it does, and it’s not necessarily a bug in the
+code, so browse the lists’ archives of the last two months, and if you
+don’t see messages about it, ask!
+
+If the behavior is correct but confusing, we think that’s a bug too, and
+you should file a bug against our documentation.
+
+For more information about the users list, the lists’ archives and the
+faq, please visit https://www.freeradius.org/list/users.html Please make
+sure to READ and RESPECT the house-rules. You will get much better
+response and much faster if you do!
+
+== Core dumps
+
+If the server (or one of the accompanying programs) core dumps, then you
+should rebuild the server as follows:
+
+```
+$ ./configure --enable-developer
+$ make
+$ make install
+```
+
+and then run the program again. You may have to to enable core dumps,
+via:
+
+```
+$ ulimit -c unlimited
+```
+
+When it core dumps, do:
+
+```
+$ gdb /path/to/executable /path/to/core/file
+```
+
+Enable logging in `gdb` via the following commands:
+
+```
+(gdb) set logging file gdb-radiusd.log
+(gdb) set logging on
+```
+
+and follow the instructions in the proceeding section.
+
+You can also enable the `panic_action` given in
+`raddb/radiusd.conf`. See the comments in that file for more details
+about automatically collecting gdb debugging information when the server
+crashes.
+
+== Debugging a live server
+
+If you can’t get a core dump, or the problem doesn’t result in a core
+dump, you may have to run the server under gdb. To do this, ensure that
+you have symbols in the binaries (i.e. a 'non-stripped' binary) by
+re-building the server as described in the previous section. Then, run
+the server under gdb as follows:
+
+```
+$ gdb radiusd
+```
+
+Enable logging in `gdb` via the following commands:
+
+```
+(gdb) set logging file gdb-radiusd.log
+(gdb) set logging on
+```
+
+Tell `gdb` to pass any necessary command-line arguments to the server:
+
+```
+(gdb) set args ...
+```
+
+Where the ``…'' are the command-line arguments you normally pass to
+radiusd. For debugging, you probably want to do:
+
+```
+(gdb) set args -fxx
+```
+
+Then, do:
+
+```
+(gdb) run
+```
+
+When something interesting happens, you can hit CTRL-C in the window,
+and you should be back at the gdb prompt:
+
+```
+(gdb)
+```
+
+And follow the instructions in the next section.
+
+== Obtaining useful information
+
+Once you have a core dump loaded into gdb, or FreeRADIUS running under
+gdb, you may use the commands below to get useful information about the
+state of the server.
+
+If the server was built with threads, you can do:
+
+```
+(gdb) info threads
+```
+
+Which will give you information about the threads. If the server isn’t
+threaded, that command-line will print a message saying so.
+
+Then, do:
+
+```
+(gdb) thread apply all bt full
+```
+
+If the server isn’t threaded, the `thread apply` section isn’t
+necessary
+
+The output should be printed to the screen, and also sent to the
+`gdb-radiusd.log` file.
+
+You should then submit the information from the log file, along with any
+server output, the output of `radiusd -xv`, and information about your
+operating system to:
+
+https://bugs.freeradius.org/
+
+Submitting it to the bug database ensures that the bug report won’t get
+forgotten, and that it will be dealt with in due course.
+
+You should provide the issue number in any mail sent to the user’s list.
+
+== Valgrind
+
+On Linux systems, `valgrind` is a useful tool that can catch certain
+classes of bugs. To use it, run the server via:
+
+```
+$ valgrind --tool=memcheck --leak-check=full radiusd -Xm
+```
+
+It will print out certain kinds of errors to the screen. There may be a
+number of errors related to OpenSSL, dlopen(), or libtldl. We cannot do
+anything about those problems. However, any errors that are inside of
+the FreeRADIUS source should be brought to our attention.
+
+== Running with `screen`
+
+If the bug is a crash of the server, and it takes a long time for the
+crash to happen, perform the following steps:
+
+* Log in as root.
+* Open a https://www.gnu.org/software/screen/[screen] session: `$ screen bash`.
+* Make sure FreeRADIUS is not running.
+* Make sure you have all the debug symbols about, or a debugable version
+of the server installed (one built with `--enable-developer` as above).
+* Configure screen to log to a file by pressing `Ctrl+a`, then `h`.
+* Type `gdb /path/to/radiusd` (or /path/to/freeradius on Debian).
+* At the `(gdb)` prompt, type `run -X`.
+* Detach from screen with `Ctrl+a`, `d`.
+* When you notice FreeRADIUS has died, reconnect to your screen session
+`$ screen -D -r`.
+* At the `(gdb)` prompt type `where` or for _lots_ of info try
+`thread apply all bt full`.
+* Tell screen to stop logging, `Ctrl+a`, `h`.
+* Logout from screen.
+
+FreeRADIUS Project, copyright 2019
--- /dev/null
+= Coding Methods
+
+The following is a short set of guidelines to follow while programming. It does
+not address coding styles, function naming methods, or debugging methods.
+Rather, it describes the processes which should go on in the programmer’s mind
+while they are programming.
+
+Coding standards apply to function names, the look of the code, and coding
+consistency. Coding methods apply to the daily practices used by the programmer
+to write code.
+
+== Comment your code
+
+If you don’t, you’ll be forced to debug it six months later, when you have no clue
+as to what it’s doing.
+
+If someone _really_ hates you, you’ll be forced to debug un-commented code that
+someone else wrote. You don’t want to do that.
+
+For FreeRADIUS, use doxygen `@`-style comments so you get the
+benefits of the developer documentation site, https://doc.freeradius.org/.
+
+== Give things reasonable names
+
+Variables and functions should have names. Calling them `x`, `xx`,
+and `xxx` makes your life hell. Even `foo` and `i` are
+problematic.
+
+Avoid smurfs. Don’t re-use struct names in field names, i. e.
+
+[source,c]
+----
+struct smurf {
+ char *smurf_pappa_smurf;
+}
+----
+
+If your code reads as full English sentences, you’re doing it right.
+
+== Check input parameters in the functions you write
+
+Your function _cannot_ do anything right if the user passed in garbage
+and you were too lazy to check for garbage input.
+
+`assert()` (`fr_assert()`) is ugly. Use it.
+
+[NOTE]
+====
+GIGO, "Garbage In, Garbage Out," is wrong. If your function gets
+garbage input, it should complain loudly and with great
+descriptiveness.
+====
+
+== Write useful error messages
+
+"Function failed" is useless as an error message. It makes debugging the code
+impossible without source-level instrumentation.
+
+If you’re going to instrument the code at source level for error messages, leave
+the error messages there, so the next sucker won’t have to do the same work all
+over again.
+
+== Check error conditions from the functions you call
+
+Your function _cannot_ do anything right if you called another function, and
+they gave you garbage output.
+
+One of the most common mistakes is:
+
+[source,c]
+----
+fp = fopen(...);
+fgetc(fp); /* core dumps! */
+----
+
+If the programmer had bothered to check for a `NULL` fp (error
+condition), then they could have produced a descriptive error message
+instead of having the program core dump.
+
+== Core dumps are for weenies
+
+If your program core dumps accidentally, you’re a bad programmer. You don’t know
+what your program is doing, or what it’s supposed to be doing when anything goes
+wrong.
+
+If it hits an `assert()` and calls `abort()`, you’re a genius. You’ve thought
+ahead to what _might_ go wrong, and put in an assertion to ensure that it fails
+in a _known manner_ when something _does_ go wrong. (As it usually does…)
+
+== Initialize your variables
+
+`memset()` (`talloc_zero()`) is your friend. `ptr = NULL` is nice,
+too.
+
+Having variables containing garbage values makes it easy for the code to do
+garbage things. The contents of local variables are inputs to your function. See
+xref:#_check_input_parameters_in_the_functions_you_write[#3].
+
+It’s also nearly impossible for you to debug any problems, as you can’t tell the
+variables with garbage values from the real ones.
+
+== Don’t allow buffer over-runs
+
+They’re usually accidental, but they cause core dumps. `strcpy()` and `strcat()`
+are ugly. Use them under duress.
+
+`sizeof()` is your friend.
+
+== `const` is your friend
+
+If you don’t mean to modify an input structure to your function, declare it
+`const`. Declare string constants `const`. It can’t hurt, and it allows more
+errors to be found at compile time.
+
+Use `const` everywhere. Once you throw a few into your code, and have it save
+you from stupid bugs, you’ll blindly throw in `const` everywhere. It’s a
+life-saver.
+
+== Use C compiler warnings
+
+Turn on all of the C compiler warnings possible. You might have to turn some off
+due to broken system header files, though. But the more warnings the merrier.
+
+Getting error messages at compile time is much preferable to getting core dumps
+at run time. See xref:#_initialize_your_variables[#7].
+
+Notice that the C compiler error messages are helpful? You should write error
+messages like this, too. See xref:#_write_useful_error_messages[#4].
+
+== Avoid UNIXisms and ASCIIisms and visualisms
+
+You don’t know under what system someone will try to run your code. Don’t demand
+that others use the same OS or character set as you use.
+
+Never assign numbers to pointers. If foo is a `char*`, and you want it to be be
+`NULL`, assign `NULL`, not `0`. The zeroth location is perfectly as addressable
+as any other on plenty of OSes. Not all the world runs on Unix (though it should
+:) ).
+
+Another common mistake is to assume that the zeroth character in the character
+set is the string terminator. Instead of terminating a string with `0`, use
+`'\0'`, which is always right. Similarly, `memset()` with the appropriate value:
+`NULL`, `'\0'`, or `0` for pointers, chars, and numbers.
+
+Don’t put tabs in string constants, either. Always use `'\t'` to represent a
+tab, instead of ASCII 9. Literal tabs are presented to readers of your code as
+arbitrary whitespace, and it’s easy to mess up.
+
+== Make conditionals explicit
+
+Though it’s legal to test `if (foo) {}` if you test against the appropriate
+value (like `NULL` or `'\0'`), your code is prettier and easier for others to
+read without having to eyeball your prototypes continuously to figure out what
+you’re doing (especially if your variables aren’t well-named). See
+xref:#_give_things_reasonable_names[#2].
+
+== Test your code
+
+Even Donald Knuth writes buggy code. You’ll never find all of the bugs in your
+code. But writing a test program definitely helps.
+
+This means that you’ll have to write your code so that it will be easily
+testable. As a result, it will look better and be easier to debug.
+
+== Hints, Tips, and Tricks
+
+This section lists many of the common `rules` associated with code submitted to
+the project. There are always exceptions… but you must have a really good reason
+for doing so.
+
+== Read the Documentation and follow the CodingStyle
+
+The FreeRADIUS server has a common coding style. Use real tabs to indent. There
+is whitespace in variable assignments (`i = 1`, not `i=1`).
+
+When in doubt, format your code to look the same as code already in the server.
+If your code deviates too much from the current style, it is likely to be
+rejected without further review, and without comment.
+
+== #ifdefs are ugly
+
+Code cluttered with `#ifdef` s is difficult to read and maintain. Don’t do it.
+Instead, put your `#ifdef` s in a header, and conditionally define `static
+inline` functions, or macros, which are used in the code. Let the compiler
+optimize away the 'no-op' case.
+
+Simple example, of poor code:
+
+[source,c]
+----
+#ifdef CONFIG_MY_FUNKINESS
+ init_my_stuff(foo);
+#endif
+----
+
+Cleaned-up example:
+
+(in header):
+
+[source,c]
+----
+#ifndef CONFIG_MY_FUNKINESS
+ static inline void init_my_stuff(char *foo) {}
+#endif
+----
+
+(in the code itself):
+
+[source,c]
+----
+init_my_stuff(dev);
+----
+
+== `static inline` is better than a macro
+
+Static inline functions are greatly preferred over macros. They provide type
+safety, have no length limitations, no formatting limitations, and under gcc
+they are as cheap as macros.
+
+Macros should only be used for cases where a static inline is clearly suboptimal
+(there a few, isolated cases of this in fast paths), or where it is impossible
+to use a static inline function (such as string-izing).
+
+`static inline` is preferred over `$$static __inline__$$`, `extern inline`, and
+`$$extern __inline__$$`.
+
+== Don’t over-design
+
+Don’t try to anticipate nebulous future cases which may or may not be useful:
+_Make it as simple as you can, and no simpler._
+
+Split up functionality as much as possible. If your code needs to do two
+unrelated things, write two functions. Mashing two kinds of work into one
+function makes the server difficult to debug and maintain.
+
--- /dev/null
+= Contributing
+
+== Submitting patches or diff’s to the FreeRADIUS project
+
+For a person or company wishing to submit a change to the FreeRADIUS
+project the process can sometimes be daunting if you’re not familiar
+with "the system." This text is a collection of suggestions which can
+greatly increase the chances of your change being accepted.
+
+Note: Only trivial patches will be accepted via email. Large patches, or
+patches that modify a number of files MUST be submitted as a
+https://github.com/FreeRADIUS/freeradius-server/pulls[pull-request via GitHub].
+
+== Hints and tips
+
+=== 1. Describe your changes
+
+Describe the technical detail of the change(s) your patch or commit
+includes.
+
+Be as specific as possible. The WORST descriptions possible include
+things like "update file X", "bug fix for file X", or "this patch
+includes updates for subsystem X. Please apply."
+
+If your description starts to get long, that’s a sign that you probably
+need to split up your commit. See the next point.
+
+=== 2. Separate your changes
+
+Separate each logical change into its own commit.
+
+For example, if your changes include both bug fixes and performance
+enhancements for a single module, separate those changes into two or
+more patches.
+
+On the other hand, if you make a single change to numerous files, group
+those changes into a single commit. Thus a single LOGICAL change is
+contained within a single commit.
+
+If one commit depends on another commit in order for a change to be
+complete, that is OK. Simply note "this commit depends on commit X" in
+the extended commit description.
+
+If your commit includes significant whitespace changes these should also
+be broken out into another, separate, commit.
+
+== Submitting patches via GitHub
+
+See the following links for more details about submitting via github:
+
+* https://help.github.com/articles/fork-a-repo
+* http://wiki.freeradius.org/contributing/GitHub
+
+== Submitting patches via email
+
+=== 1. diff -u
+
+Use `diff -u` or `diff -urN` to create patches.
+
+All changes to the source occur in the form of patches, as generated by
+diff(1). When creating your patch, make sure to create it in unified
+diff format, as supplied by the `-u` argument to diff(1). Patches
+should be based in the root source directory, not in any lower
+subdirectory.
+
+To create a patch for a single file, it is often sufficient to do::
+
+```
+SRCTREE=/home/user/src/freeradiusd/
+MYFILE=src/modules/rlm_foo/foo.c
+
+cd $SRCTREE
+cp $MYFILE $MYFILE.orig
+vi $MYFILE # make your change
+diff -u $MYFILE.orig $MYFILE > /tmp/patch
+```
+
+To create a patch for multiple files, you should unpack a `vanilla`,
+or unmodified source tree, and generate a diff against your own source
+tree. For example:
+
+```
+MYSRC=/home/user/src/freeradiusd-feature/
+
+gunzip freeradiusd-version.tar.gz
+tar xvf freeradiusd-version.tar
+diff -urN freeradiusd-version $MYSRC > ~/feature-version.patch
+```
+
+=== 2. Select e-mail destination
+
+If you are on the developers mailing list, send the patch there.
+mailto:freeradius-devel@lists.freeradius.org[freeradius-devel@lists.freeradius.org]
+
+Otherwise, send the patch to
+mailto:patches@freeradius.org[patches@freeradius.org]
+
+=== 3. No MIME, no links, no compression, no attachments. Just plain text
+
+The developers need to be able to read and comment on the changes you
+are submitting. It is important for a developer to be able to `quote`
+your changes, using standard e-mail tools, so that they may comment on
+specific portions of your code.
+
+For this reason, all patches should be submitting e-mail `inline`.
+
+Do not attach the patch as a MIME attachment, compressed or not. Many
+popular e-mail applications will not always transmit a MIME attachment
+as plain text, making it impossible to comment on your code. A MIME
+attachment also takes a bit more time to process, decreasing the
+likelihood of your MIME-attached change being accepted.
+
+Compressed patches are generally rejected outright. If the developer has
+to do additional work to read your patch, the odds are that it will be
+ignored completely.
+
+=== 4. E-mail size
+
+Large changes are not appropriate for mailing lists, and some
+maintainers. If your patch, exceeds 5Kb in size, you must submit the
+patch via GitHub instead.
+
+=== 5. Name the version of the server
+
+It is important to note, either in the subject line or in the patch
+description, the server version to which this patch applies.
--- /dev/null
+= Code Coverage
+
+We use the link:https://gcc.gnu.org/onlinedocs/gcc/Gcov-Intro.html#Gcov-Intro[gcov] tool to know our tests coverage.
+
+[source,shell]
+----
+$ make clean
+$ make coverage
+----
+
+If completed with success, a pretty report will be available in `${source_tree}/build/coverage/index.html`
--- /dev/null
+= FreeRADIUS Development
+
+List with some usual howtos for FreeRADIUS.
+
+Programming reference documentation can be found at the
+https://doc.freeradius.org/[Doxygen] site.
+
+== Topics
+
+* xref:bugs.adoc[Bugs]
+* xref:coding-methods.adoc[Coding Methods]
+* xref:coverage.adoc[Code Coverage]
+* xref:profile.adoc[Profiling]
+* xref:contributing.adoc[Contributing]
+* xref:release-method.adoc[Release Method]
+
+Also see the xref:installation:dependencies.adoc[build
+dependencies] page.
--- /dev/null
+= Profiling
+
+Build with gperftools, and ensure that it's built:
+
+[source,shell]
+----
+$ grep profile Make.inc
+GPERFTOOLS_LIBS = -lprofiler
+----
+
+Run your test using the profiling tools. One signal will start the
+profiling, another will stop it.
+
+[source,shell]
+----
+env CPUPROFILE=/tmp/freeradius.prof CPUPROFILESIGNAL=12 freeradius ...
+killall -12 freeradius
+ ... wait ...
+killall -12 freeradius
+----
+
+View the results
+
+[source,shell]
+----
+pprof --text /path/to/freeradius /tmp/freeradius.prof
+----
+
+or as a graph
+
+[source,shell]
+----
+pprof --gv /path/to/freeradius /tmp/freeradius.prof
+----
+
+or as cachgrind output
+
+[source,shell]
+----
+pprof --cachegrind /path/to/freeradius /tmp/freeradius.prof
+----
--- /dev/null
+= Release Method
+
+== Topics
+
+[arabic]
+. As of 2.0, the release process is much simpler. Edit the Changelog
+with the version number and any last updates.
+
+```
+# vi doc/ChangeLog
+# git commit doc/ChangeLog
+```
+
+[arabic, start=2]
+. Change version numbers in the VERSION file:
+
+```
+# vi VERSION
+# git commit VERSION
+```
+
+[arabic, start=3]
+. Make the files
+
+NOTE: It also does `make dist-check`, which checks the build rules for
+various packages.
+
+```
+# make dist
+```
+
+[arabic, start=4]
+. Validate that the packages are OK. If so, tag the release.
+
+NOTE: This does NOT actually do the tagging! You will have to run the
+command it prints out yourself.
+
+```
+# make dist-tag
+```
+
+[arabic, start=5]
+. Sign the packages. You will need the correct GPG key for this to work.
+
+```
+# make dist-sign
+```
+
+[arabic, start=6]
+. Push to the FTP site. You will need write access to the FTP site for
+this to work.
+
+```
+# make dist-publish
+```