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