diff --git a/apps/app_directory.c b/apps/app_directory.c index be76d4b35b035e74876f84669d099be32cd822d1..e22a2ccb400913a82acbca56b79bb38e67c54e90 100755 --- a/apps/app_directory.c +++ b/apps/app_directory.c @@ -262,3 +262,8 @@ int usecount(void) STANDARD_USECOUNT(res); return res; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/apps/app_echo.c b/apps/app_echo.c index 370dc68636e6b7d183f038d3f37dfee0c0394df3..7d0647d04b052e0af5e7dcbda6e9c5d66b564c7f 100755 --- a/apps/app_echo.c +++ b/apps/app_echo.c @@ -78,3 +78,8 @@ int usecount(void) STANDARD_USECOUNT(res); return res; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/apps/app_playback.c b/apps/app_playback.c index d7e023d944b79b799b363c8f63c7ae5e0174c45a..945686b2ca21ef194c75b93292771fb6272f2131 100755 --- a/apps/app_playback.c +++ b/apps/app_playback.c @@ -75,3 +75,8 @@ int usecount(void) STANDARD_USECOUNT(res); return res; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/apps/app_skel.c b/apps/app_skel.c index 419b8f40a0587d578b0cc939461f89fca526ce17..8ca411305b9e33589af60768707016dbeae7d873 100755 --- a/apps/app_skel.c +++ b/apps/app_skel.c @@ -68,3 +68,8 @@ int usecount(void) STANDARD_USECOUNT(res); return res; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/apps/app_system.c b/apps/app_system.c index 7e140a427833c0a922ac6ef08548e59aea0aace6..9915cbd965793288ef612c6911de3ed746d4a314 100755 --- a/apps/app_system.c +++ b/apps/app_system.c @@ -80,3 +80,8 @@ int usecount(void) STANDARD_USECOUNT(res); return res; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/channels/chan_modem_aopen.c b/channels/chan_modem_aopen.c index f344cb149bc6638bfe31a3351a4cf2b4f4b2b5e6..37c5a8b7f699c1043c6f62091cd9e6b20d9bcb46 100755 --- a/channels/chan_modem_aopen.c +++ b/channels/chan_modem_aopen.c @@ -478,3 +478,7 @@ char *description() return desc; } +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/channels/chan_modem_i4l.c b/channels/chan_modem_i4l.c index 3a8dbd8c8a4eb4dbe7bdc17bd85da7f3d979ad84..f1e521adfd4caf1d954f0a53c2ab1583a5c0b7a8 100755 --- a/channels/chan_modem_i4l.c +++ b/channels/chan_modem_i4l.c @@ -358,6 +358,8 @@ static struct ast_frame *i4l_read(struct ast_modem_pvt *p) if (f) break; } + if (f) + return f; /* If we get here, we have a complete voice frame */ p->fr.frametype = AST_FRAME_VOICE; p->fr.subclass = AST_FORMAT_SLINEAR; @@ -570,3 +572,7 @@ char *description() return desc; } +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/codecs/codec_mp3_d.c b/codecs/codec_mp3_d.c index 95e1fb51fc8e1a9e19ba715739ccd9e34548ba64..aad6d75703cd2e08ef640f810d81b51ef1ce439f 100755 --- a/codecs/codec_mp3_d.c +++ b/codecs/codec_mp3_d.c @@ -321,3 +321,8 @@ int usecount(void) STANDARD_USECOUNT(res); return res; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/formats/format_g723.c b/formats/format_g723.c index 83144376f866d85571dc351e8a4739071d1e8b1f..c437addcd115963d9c0587546f5139df71d2824f 100755 --- a/formats/format_g723.c +++ b/formats/format_g723.c @@ -350,3 +350,8 @@ char *description() return desc; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/formats/format_mp3.c b/formats/format_mp3.c index 85abdbc1b9a3318417c5bdb151f21846244629c7..a3e25d45bc202ca3d34b1bd19d65a6d73414a57e 100755 --- a/formats/format_mp3.c +++ b/formats/format_mp3.c @@ -293,3 +293,8 @@ char *description() return desc; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/formats/format_wav.c b/formats/format_wav.c index 9ba4fdc22a0e21acfbc24e6922193861d2ea7278..071c24f26fccfb1e8dd0c63dd9253acc33d7580d 100755 --- a/formats/format_wav.c +++ b/formats/format_wav.c @@ -353,3 +353,8 @@ char *description() return desc; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/formats/format_wav_gsm.c b/formats/format_wav_gsm.c index b901a4028890cff6ac96214fd3d025767446a5d7..94e2bffd057911f57dab877f4425cc00a2db10c5 100755 --- a/formats/format_wav_gsm.c +++ b/formats/format_wav_gsm.c @@ -584,3 +584,8 @@ char *description() return desc; } + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/include/asterisk/module.h b/include/asterisk/module.h index e7bda62d6b8cdec529f39376fe97e6fa472cd897..9a8a7153cc12d7ee5f2a1020e044dcae8786446c 100755 --- a/include/asterisk/module.h +++ b/include/asterisk/module.h @@ -25,6 +25,17 @@ int unload_module(void); /* Cleanup all module structures, sockets, etc */ int usecount(void); /* How many channels provided by this module are in use? */ char *description(void); /* Description of this module */ +char *key(void); /* Return the below mentioned key, unmodified */ + +int reload(void); + +#define ASTERISK_GPL_KEY \ + "This paragraph is Copyright (C) 2000, Linux Support Services, Inc. \ +In order for your module to load, it must return this key via a function \ +called \"key\". Any code which includes this paragraph must be licensed under \ +the GNU General Public License version 2 or later (at your option). Linux \ +Support Services, Inc. reserves the right to allow other parties to license \ +this paragraph under other terms as well." #define AST_MODULE_CONFIG "modules.conf" /* Module configuration file */ diff --git a/loader.c b/loader.c index 63c44df40c917c24aeb1015439917a165755d303..b216a07bc97e2b8b75d2f1c0961709cf9fa492fd 100755 --- a/loader.c +++ b/loader.c @@ -21,20 +21,65 @@ #include <asterisk/config.h> #include <asterisk/logger.h> #include <dlfcn.h> +#include <asterisk/md5.h> #define __USE_GNU #include <pthread.h> #include "asterisk.h" +static char expected_key[] = +{ 0x8e, 0x93, 0x22, 0x83, 0xf5, 0xc3, 0xc0, 0x75, + 0xff, 0x8b, 0xa9, 0xbe, 0x7c, 0x43, 0x74, 0x63 }; + struct module { int (*load_module)(void); int (*unload_module)(void); int (*usecount)(void); char *(*description)(void); + char *(*key)(void); + int (*reload)(void); void *lib; char resource[256]; struct module *next; }; +static int printdigest(unsigned char *d) +{ + int x; + char buf[256]; + char buf2[16]; + snprintf(buf, sizeof(buf), "Unexpected signature:"); + for (x=0;x<16;x++) { + snprintf(buf2, sizeof(buf2), " %02x", *(d++)); + strcat(buf, buf2); + } + strcat(buf, "\n"); + ast_log(LOG_DEBUG, buf); + return 0; +} + +static int key_matches(char *key1, char *key2) +{ + int match = 1; + int x; + for (x=0;x<16;x++) { + match &= (key1[x] == key2[x]); + } + return match; +} + +static int verify_key(char *key) +{ + struct MD5Context c; + char digest[16]; + MD5Init(&c); + MD5Update(&c, key, strlen(key)); + MD5Final(digest, &c); + if (key_matches(expected_key, digest)) + return 0; + printdigest(digest); + return -1; +} + static struct loadupdate { int (*updater)(void); struct loadupdate *next; @@ -94,6 +139,7 @@ int ast_load_resource(char *resource_name) struct module *m; int flags=0; char *val; + char *key; int o; struct ast_config *cfg; /* Keep the module file parsing silent */ @@ -158,6 +204,21 @@ int ast_load_resource(char *resource_name) ast_log(LOG_WARNING, "No description in module %s\n", fn); errors++; } + m->key = dlsym(m->lib, "key"); + if (!m->key) { + ast_log(LOG_WARNING, "No key routine in module %s\n", fn); + errors++; + } + m->reload = dlsym(m->lib, "reload"); + if (m->key && !(key = m->key())) { + ast_log(LOG_WARNING, "Key routine returned NULL in module %s\n", fn); + errors++; + } else + key = NULL; + if (key && verify_key(key)) { + ast_log(LOG_WARNING, "Unexpected key returned by module %s\n", fn); + errors++; + } if (errors) { ast_log(LOG_WARNING, "%d error(s) loading module %s, aborted\n", errors, fn); dlclose(m->lib); @@ -175,6 +236,7 @@ int ast_load_resource(char *resource_name) ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", fn, m->description()); } m->next = module_list; + module_list = m; pthread_mutex_unlock(&modlock); if ((res = m->load_module())) { diff --git a/pbx/pbx_gtkconsole.c b/pbx/pbx_gtkconsole.c index 52a4ecb980bb51350cb8f6987d508e6e1d7d7e18..f8f233cf84a9ec0eaa83395737cd281daf1c486e 100755 --- a/pbx/pbx_gtkconsole.c +++ b/pbx/pbx_gtkconsole.c @@ -494,3 +494,8 @@ char *description(void) { return dtext; } + +char *key(void) +{ + return ASTERISK_GPL_KEY; +}