lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | Starting with version 2.3.10, pppd includes support for `plugins' - |
| 2 | pieces of code which can be loaded into pppd at runtime and which can |
| 3 | affect its behaviour in various ways. The idea of plugins is to |
| 4 | provide a way for people to customize the behaviour of pppd without |
| 5 | having to either apply local patches to each version or get their |
| 6 | patches accepted into the standard distribution. |
| 7 | |
| 8 | A plugin is a standard shared library object, typically with a name |
| 9 | ending in .so. They are loaded using the standard dlopen() library |
| 10 | call, so plugins are only supported on systems which support shared |
| 11 | libraries and the dlopen call. At present pppd is compiled with |
| 12 | plugin support only under Linux and Solaris. |
| 13 | |
| 14 | Plugins are loaded into pppd using the `plugin' option, which takes |
| 15 | one argument, the name of a shared object file. The plugin option is |
| 16 | a privileged option. If the name given does not contain a slash, pppd |
| 17 | will look in the /usr/lib/pppd/<version> directory for the file, where |
| 18 | <version> is the version number of pppd, for example, 2.4.2. I |
| 19 | suggest that you either give the full path name of the shared object |
| 20 | file or just the base name; if you don't, it may be possible for |
| 21 | unscrupulous users to substitute another shared object file for the |
| 22 | one you mean to load, e.g. by setting the LD_LIBRARY_PATH variable. |
| 23 | |
| 24 | Plugins are usually written in C and compiled and linked to a shared |
| 25 | object file in the appropriate manner for your platform. Using gcc |
| 26 | under Linux, a plugin called `xyz' could be compiled and linked with |
| 27 | the following commands: |
| 28 | |
| 29 | gcc -c -O xyz.c |
| 30 | gcc -shared -o xyz.so xyz.o |
| 31 | |
| 32 | There are some example plugins in the pppd/plugins directory in the |
| 33 | ppp distribution. Currently there is one example, minconn.c, which |
| 34 | implements a `minconnect' option, which specifies a minimum connect |
| 35 | time before the idle timeout applies. |
| 36 | |
| 37 | Plugins can access global variables within pppd, so it is useful for |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 38 | them to #include "pppd.h" from the pppd source directory. Other |
| 39 | header files can be included such as chap.h, mppe.h, and upap.h as |
| 40 | needed per project. |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 41 | |
| 42 | Every plugin must contain a global procedure called `plugin_init'. |
| 43 | This procedure will get called (with no arguments) immediately after |
| 44 | the plugin is loaded. Every plugin should also contain a variable |
| 45 | called pppd_version declared as follows: |
| 46 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 47 | char pppd_version[] = PPPD_VERSION; |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 48 | |
| 49 | If this declaration is included, pppd will not load the module if its |
| 50 | version number differs from that compiled into the plugin binary. |
| 51 | |
| 52 | Plugins can affect the behaviour of pppd in at least four ways: |
| 53 | |
| 54 | 1. They can add extra options which pppd will then recognize. This is |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 55 | done by calling the ppp_add_options() procedure with a pointer to an |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 56 | array of option_t structures. The last entry in the array must |
| 57 | have its name field set to NULL. |
| 58 | |
| 59 | 2. Pppd contains `hook' variables which are procedure pointers. If a |
| 60 | given hook is not NULL, pppd will call the procedure it points to |
| 61 | at the appropriate point in its processing. The plugin can set any |
| 62 | of these hooks to point to its own procedures. See below for a |
| 63 | description of the hooks which are currently implemented. |
| 64 | |
| 65 | 3. Plugin code can call any global procedures and access any global |
| 66 | variables in pppd. |
| 67 | |
| 68 | 4. Plugins can register procedures to be called when particular events |
| 69 | occur, using the `notifier' mechanism in pppd. The differences |
| 70 | between hooks and notifiers are that a hook will only call one |
| 71 | function, whereas a notifier can call an arbitrary number, and that |
| 72 | a hook usually returns some value to pppd, whereas a notifier |
| 73 | function returns nothing. |
| 74 | |
| 75 | Here is a list of the currently implemented hooks in pppd. |
| 76 | |
| 77 | |
| 78 | int (*idle_time_hook)(struct ppp_idle *idlep); |
| 79 | |
| 80 | The idle_time_hook is called when the link first comes up (i.e. when |
| 81 | the first network protocol comes up) and at intervals thereafter. On |
| 82 | the first call, the idlep parameter is NULL, and the return value is |
| 83 | the number of seconds before pppd should check the link activity, or 0 |
| 84 | if there is to be no idle timeout. |
| 85 | |
| 86 | On subsequent calls, idlep points to a structure giving the number of |
| 87 | seconds since the last packets were sent and received. If the return |
| 88 | value is > 0, pppd will wait that many seconds before checking again. |
| 89 | If it is <= 0, that indicates that the link should be terminated due |
| 90 | to lack of activity. |
| 91 | |
| 92 | |
| 93 | int (*holdoff_hook)(void); |
| 94 | |
| 95 | The holdoff_hook is called when an attempt to bring up the link fails, |
| 96 | or the link is terminated, and the persist or demand option was used. |
| 97 | It returns the number of seconds that pppd should wait before trying |
| 98 | to reestablish the link (0 means immediately). |
| 99 | |
| 100 | |
| 101 | int (*pap_check_hook)(void); |
| 102 | int (*pap_passwd_hook)(char *user, char *passwd); |
| 103 | int (*pap_auth_hook)(char *user, char *passwd, char **msgp, |
| 104 | struct wordlist **paddrs, |
| 105 | struct wordlist **popts); |
| 106 | void (*pap_logout_hook)(void); |
| 107 | |
| 108 | These hooks are designed to allow a plugin to replace the normal PAP |
| 109 | password processing in pppd with something different (e.g. contacting |
| 110 | an external server). |
| 111 | |
| 112 | The pap_check_hook is called to check whether there is any possibility |
| 113 | that the peer could authenticate itself to us. If it returns 1, pppd |
| 114 | will ask the peer to authenticate itself. If it returns 0, pppd will |
| 115 | not ask the peer to authenticate itself (but if authentication is |
| 116 | required, pppd may exit, or terminate the link before network protocol |
| 117 | negotiation). If it returns -1, pppd will look in the pap-secrets |
| 118 | file as it would normally. |
| 119 | |
| 120 | The pap_passwd_hook is called to determine what username and password |
| 121 | pppd should use in authenticating itself to the peer with PAP. The |
| 122 | user string will already be initialized, by the `user' option, the |
| 123 | `name' option, or from the hostname, but can be changed if necessary. |
| 124 | MAXNAMELEN bytes of space are available at *user, and MAXSECRETLEN |
| 125 | bytes of space at *passwd. If this hook returns 0, pppd will use the |
| 126 | values at *user and *passwd; if it returns -1, pppd will look in the |
| 127 | pap-secrets file, or use the value from the +ua or password option, as |
| 128 | it would normally. |
| 129 | |
| 130 | The pap_auth_hook is called to determine whether the username and |
| 131 | password supplied by the peer are valid. user and passwd point to |
| 132 | null-terminated strings containing the username and password supplied |
| 133 | by the peer, with non-printable characters converted to a printable |
| 134 | form. The pap_auth_hook function should set msg to a string to be |
| 135 | returned to the peer and return 1 if the username/password was valid |
| 136 | and 0 if not. If the hook returns -1, pppd will look in the |
| 137 | pap-secrets file as usual. |
| 138 | |
| 139 | If the username/password was valid, the hook can set *paddrs to point |
| 140 | to a wordlist containing the IP address(es) which the peer is |
| 141 | permitted to use, formatted as in the pap-secrets file. It can also |
| 142 | set *popts to a wordlist containing any extra options for this user |
| 143 | which pppd should apply at this point. |
| 144 | |
| 145 | The pap_logout_hook is called when the link is terminated, instead of |
| 146 | pppd's internal `plogout' function. It can be used for accounting |
| 147 | purposes. This hook is deprecated and will be replaced by a notifier. |
| 148 | |
| 149 | |
| 150 | int (*chap_check_hook)(void); |
| 151 | int (*chap_passwd_hook)(char *user, char *passwd); |
| 152 | int (*chap_verify_hook)(char *name, char *ourname, int id, |
| 153 | struct chap_digest_type *digest, |
| 154 | unsigned char *challenge, unsigned char *response, |
| 155 | char *message, int message_space) |
| 156 | |
| 157 | These hooks are designed to allow a plugin to replace the normal CHAP |
| 158 | password processing in pppd with something different (e.g. contacting |
| 159 | an external server). |
| 160 | |
| 161 | The chap_check_hook is called to check whether there is any possibility |
| 162 | that the peer could authenticate itself to us. If it returns 1, pppd |
| 163 | will ask the peer to authenticate itself. If it returns 0, pppd will |
| 164 | not ask the peer to authenticate itself (but if authentication is |
| 165 | required, pppd may exit, or terminate the link before network protocol |
| 166 | negotiation). If it returns -1, pppd will look in the chap-secrets |
| 167 | file as it would normally. |
| 168 | |
| 169 | The chap_passwd_hook is called to determine what password |
| 170 | pppd should use in authenticating itself to the peer with CHAP. The |
| 171 | user string will already be initialized, by the `user' option, the |
| 172 | `name' option, or from the hostname, but can be changed if necessary. |
| 173 | This hook is called only if pppd is a client, not if it is a server. |
| 174 | |
| 175 | MAXSECRETLEN bytes of space are available at *passwd. If this hook |
| 176 | returns 0, pppd will use the value *passwd; if it returns -1, pppd |
| 177 | will fail to authenticate. |
| 178 | |
| 179 | The chap_verify_hook is called to determine whether the peer's |
| 180 | response to our CHAP challenge is valid -- it should return 1 if valid |
| 181 | or 0 if not. The parameters are: |
| 182 | |
| 183 | * name points to a null-terminated string containing the username |
| 184 | supplied by the peer, or the remote name specified with the |
| 185 | "remotename" option. |
| 186 | * ourname points to a null-terminated string containing the name of |
| 187 | the local machine (the hostname, or the name specified with the |
| 188 | "name" option). |
| 189 | * id is the value of the id field from the challenge. |
| 190 | * digest points to a chap_digest_type struct, which contains an |
| 191 | identifier for the type of digest in use plus function pointers for |
| 192 | functions for dealing with digests of that type. |
| 193 | * challenge points to the challenge as a counted string (length byte |
| 194 | followed by the actual challenge bytes). |
| 195 | * response points to the response as a counted string. |
| 196 | * message points to an area of message_space bytes in which to store |
| 197 | any message that should be returned to the peer. |
| 198 | |
| 199 | |
| 200 | int (*null_auth_hook)(struct wordlist **paddrs, |
| 201 | struct wordlist **popts); |
| 202 | |
| 203 | This hook allows a plugin to determine what the policy should be if |
| 204 | the peer refuses to authenticate when it is requested to. If the |
| 205 | return value is 0, the link will be terminated; if it is 1, the |
| 206 | connection is allowed to proceed, and in this case *paddrs and *popts |
| 207 | can be set as for pap_auth_hook, to specify what IP addresses are |
| 208 | permitted and any extra options to be applied. If the return value is |
| 209 | -1, pppd will look in the pap-secrets file as usual. |
| 210 | |
| 211 | |
| 212 | void (*ip_choose_hook)(u_int32_t *addrp); |
| 213 | |
| 214 | This hook is called at the beginning of IPCP negotiation. It gives a |
| 215 | plugin the opportunity to set the IP address for the peer; the address |
| 216 | should be stored in *addrp. If nothing is stored in *addrp, pppd will |
| 217 | determine the peer's address in the usual manner. |
| 218 | |
| 219 | |
| 220 | int (*allowed_address_hook)(u_int32_t addr) |
| 221 | |
| 222 | This hook is called to see if a peer is allowed to use the specified |
| 223 | address. If the hook returns 1, the address is accepted. If it returns |
| 224 | 0, the address is rejected. If it returns -1, the address is verified |
| 225 | in the normal away against the appropriate options and secrets files. |
| 226 | |
| 227 | |
| 228 | void (*snoop_recv_hook)(unsigned char *p, int len) |
| 229 | void (*snoop_send_hook)(unsigned char *p, int len) |
| 230 | |
| 231 | These hooks are called whenever pppd receives or sends a packet. The |
| 232 | packet is in p; its length is len. This allows plugins to "snoop in" |
| 233 | on the pppd conversation. The hooks may prove useful in implmenting |
| 234 | L2TP. |
| 235 | |
| 236 | |
| 237 | void (*multilink_join_hook)(); |
| 238 | |
| 239 | This is called whenever a new link completes LCP negotiation and joins |
| 240 | the bundle, if we are doing multilink. |
| 241 | |
| 242 | |
| 243 | A plugin registers itself with a notifier by declaring a procedure of |
| 244 | the form: |
| 245 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 246 | void (ppp_notify_fn)(void *opaque, int arg); |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 247 | |
| 248 | and then registering the procedure with the appropriate notifier with |
| 249 | a call of the form |
| 250 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 251 | ppp_add_notify(ppp_notify_t, ppp_notify_fn, opaque); |
| 252 | |
| 253 | The ppp_notify_t is an enumerated type that describes which notifier |
| 254 | to attach the function to. Example: NF_EXIT, NF_SIGNALED, NF_IP_UP |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 255 | |
| 256 | The `opaque' parameter in the add_notifier call will be passed to |
| 257 | my_notify_proc every time it is called. The `arg' parameter to |
| 258 | my_notify_proc depends on the notifier. |
| 259 | |
| 260 | A notify procedure can be removed from the list for a notifier with a |
| 261 | call of the form |
| 262 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 263 | ppp_del_notify(ppp_notify_t, ppp_notify_fn, opaque); |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 264 | |
| 265 | Here is a list of the currently-implemented notifiers in pppd. |
| 266 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 267 | * NF_PID_CHANGE. This notifier is called in the parent when pppd has |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 268 | forked and the child is continuing pppd's processing, i.e. when pppd |
| 269 | detaches from its controlling terminal. The argument is the pid of |
| 270 | the child. |
| 271 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 272 | * NF_PHASE_CHANGE. This is called when pppd moves from one phase of |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 273 | operation to another. The argument is the new phase number. |
| 274 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 275 | * NF_EXIT. This is called just before pppd exits. The argument is |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 276 | the status with which pppd will exit (i.e. the argument to exit()). |
| 277 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 278 | * NF_SIGNALED. This is called when a signal is received, from within |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 279 | the signal handler. The argument is the signal number. |
| 280 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 281 | * NF_IP_UP. This is called when IPCP has come up. |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 282 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 283 | * NF_IP_DOWN. This is called when IPCP goes down. |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 284 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 285 | * NF_IPV6_UP. This is called when IP6CP has come up. |
| 286 | |
| 287 | * NF_IPV6_DOWN. This is called when IP6CP goes down. |
| 288 | |
| 289 | * NF_AUTH_UP. This is called when the peer has successfully |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 290 | authenticated itself. |
| 291 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 292 | * NF_LINK_DOWN. This is called when the link goes down. |
| 293 | |
| 294 | * NF_FORK. Called for each time pppd exists as a new process (child). |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 295 | |
| 296 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 297 | Regarding MPPE keys and key-material for 2.5.0 release |
lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 298 | |
xf.li | 8402749 | 2024-04-09 00:17:51 -0700 | [diff] [blame^] | 299 | Sometimes it is necessary for a plugin to access details related to |
| 300 | the authentication process. The NF_AUTH_UP callback notifier (client only) |
| 301 | allows a plugin to inspect e.g. key details after authentication has been |
| 302 | completed, but before the key material is cleared from memory for security |
| 303 | reasons. |
| 304 | |
| 305 | There are in particularly 3 functions that allow one to inspect these |
| 306 | keys: |
| 307 | |
| 308 | * bool mppe_keys_isset() |
| 309 | * int mppe_get_recv_key(unsigned char *key, int length) |
| 310 | * int mppe_get_send_key(unsigned char *key, int length) |
| 311 | |
| 312 | The first function indicates whether or not the key material is set and |
| 313 | is valid. The two latter functions will allow one to obtain a copy |
| 314 | of the respective receive and send keys. The return value of these |
| 315 | functions is the length of the valid key material. For security reasons, |
| 316 | one should take care to clear these copies when work is complete. The |
| 317 | max length of MPPE receive ands send keys are up to 32 bytes long, or |
| 318 | of MPPE_MAX_KEY_SIZE length. |
| 319 | |
| 320 | The previous definitions of MPPE_MAX_KEY_LEN is the maximum length in |
| 321 | which the Linux kernel will accept for MPPE key lengths. Plugins would |
| 322 | access the MPPE keys directly via the: |
| 323 | |
| 324 | extern u_char mppe_send_key[MPPE_MAX_KEY_LEN] |
| 325 | extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN] |
| 326 | |
| 327 | variables. The 2.5.0 release prohibits the direct access of these |
| 328 | variables by making them static and private in favor of using the new |
| 329 | API. |
| 330 | |
| 331 | ## $Id: PLUGINS,v 1.8 2008/06/15 07:02:18 paulus Exp $ ## |