1 /*
2  * Copyright (C) 2001, 2002, and 2003  Roy Keene
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  *      email: dact@rkeene.org
19  */
20 
21 
22 #include "dact.h"
23 #include "module.h"
24 #ifdef USE_MODULES
25 #ifdef HAVE_DLFCN_H
26 #include <dlfcn.h>
27 #endif
28 #include <stdio.h>
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #endif
32 #ifdef HAVE_STDLIB_H
33 #include <stdlib.h>
34 #endif
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #include <fcntl.h>
39 #ifdef HAVE_SYS_TYPES_H
40 #include <sys/types.h>
41 #endif
42 #ifdef HAVE_SYS_STAT_H
43 #include <sys/stat.h>
44 #endif
45 #ifdef HAVE_DIRENT_H
46 #include <dirent.h>
47 #endif
48 #include "algorithms.h"
49 #include "ciphers.h"
50 #include "parse.h"
51 #include "net.h"
52 #include "ui.h"
53 
54 char moduledirectory[2048] = "@@HOME@@/.dact/@@OSNM@@-@@ARCH@@/";
55 void *modules[256];
56 int modules_initialized = 0;
57 int modules_count = 0;
58 
init_modules(void)59 int init_modules (void) {
60 	int i;
61 
62 	if (modules_initialized!=0) return(DACT_MOD_FAIL);
63 	modules_initialized=1;
64 
65 	for (i=0;i<256;i++) {
66 		modules[i]=NULL;
67 	}
68 	return(DACT_MOD_OK);
69 }
70 
unload_modules(void)71 int unload_modules (void) {
72 	int i;
73 
74 	if (modules_initialized==0) return(DACT_MOD_FAIL);
75 
76 	for (i=0;i<256;i++) {
77 		if (modules[i]!=NULL)
78 			dlclose(modules[i]);
79 	}
80 	return(DACT_MOD_OK);
81 }
82 
load_modules_all(const unsigned char * options)83 int load_modules_all(const unsigned char *options) {
84 #ifdef HAVE_DIRENT_H
85 	struct dirent *dinfo;
86 	char *mdircpy, *tmpbuf, *mbuf, *fname, fullfname[1024];
87 	DIR *dirtype;
88 
89 	mdircpy=parse_url_subst(moduledirectory, "");
90 	mbuf=mdircpy;
91 	while ((tmpbuf=strsep(&mbuf, ":"))) {
92 		if ((dirtype=opendir(tmpbuf))==NULL) continue;
93 		while ((dinfo=readdir(dirtype))!=NULL) {
94 			fname=dinfo->d_name;
95 			if (strcmp(fname+strlen(fname)-3,".so")==0) {
96 				strncpy(fullfname, tmpbuf, sizeof(fullfname));
97 				strncat(fullfname, "/", sizeof(fullfname)-strlen(fullfname));
98 				strncat(fullfname, fname, sizeof(fullfname)-strlen(fullfname));
99 				load_module(fullfname, options);
100 			}
101 		}
102 		closedir(dirtype);
103 	}
104 	free(mdircpy);
105 #else
106 	PRINTERR("I don't know how to handle this.")
107 #endif
108 	return(DACT_MOD_OK);
109 }
110 
load_module(char * modulename,const unsigned char * options)111 int load_module (char *modulename, const unsigned char *options) {
112 	char modulefile[256], *tmpbuf, *mbuf, *mdircpy;
113 	void *mh=NULL;
114 	uint32_t algo_num, module_type=DACT_MOD_TYPE_COMP;
115 	uint32_t dc_ver=0, dc_req=0, dact_ver;
116 	char *dc_url_get=NULL, *dc_url_ver=NULL, *dc_sign=NULL;
117 
118 	if (strchr(modulename,'/')==NULL) {
119 		mdircpy=parse_url_subst(moduledirectory, "");
120 		mbuf=mdircpy;
121 		while ((tmpbuf=strsep(&mbuf, ":"))) {
122 			snprintf(modulefile, sizeof(modulefile)-1, "%s/%s.so",tmpbuf,modulename);
123 			if ((mh=dlopen(modulefile, RTLD_GLOBAL|RTLD_NOW))!=NULL) break;
124 		}
125 		free(mdircpy);
126 	} else {
127 		strncpy(modulefile, modulename, sizeof(modulefile)-1);
128 		if ((mh=dlopen(modulefile, RTLD_GLOBAL|RTLD_NOW))==NULL) {
129 			PRINTERR("Could not load module.");
130 			return(DACT_MOD_FAIL);
131 		}
132 	}
133 	if (!mh) return(DACT_MOD_FAIL);
134 
135 	if (dlsym(mh,"DC_NUM")==NULL \
136 	|| dlsym(mh, "DC_NAME")==NULL \
137 	|| dlsym(mh, "DC_ALGO")==NULL) {
138 		dact_ui_status(DACT_UI_LVL_SPEC, modulefile);
139 		dact_ui_status_append(DACT_UI_LVL_SPEC, " is not a dact module.");
140 		dlclose(mh);
141 		return(DACT_MOD_FAIL);
142 	}
143 
144 	if (dlsym(mh, "DC_TYPE")!=NULL) {
145 		memcpy(&module_type,dlsym(mh,"DC_TYPE"),sizeof(module_type));
146 	}
147 
148 	memcpy(&algo_num,dlsym(mh,"DC_NUM"),sizeof(algo_num));
149 
150 	if (dlsym(mh, "DC_VER")!=NULL) memcpy(&dc_ver, dlsym(mh, "DC_VER"), sizeof(dc_ver));
151 	if (dlsym(mh, "DC_REQUIRE")!=NULL) memcpy(&dc_req, dlsym(mh, "DC_REQUIRE"), sizeof(dc_req));
152 	if (dlsym(mh, "DC_URL_GET")!=NULL) memcpy(&dc_url_get, dlsym(mh, "DC_URL_GET"), sizeof(dc_url_get));
153 	if (dlsym(mh, "DC_URL_VER")!=NULL) memcpy(&dc_url_ver, dlsym(mh, "DC_URL_VER"), sizeof(dc_url_ver));
154 	if (dlsym(mh, "DC_SIGN")!=NULL) memcpy(&dc_sign, dlsym(mh, "DC_SIGN"), sizeof(dc_sign));
155 
156 	if (dc_url_get!=NULL && dc_url_ver!=NULL && dc_ver!=0 && modulename[0]!='/') {
157 		dact_upgrade_file(modulename, dc_url_get, dc_url_ver, dc_ver, NULL, options);
158 	}
159 
160 	if (dc_req!=0) {
161 		dact_ver=(DACT_VER_MAJOR<<16)|(DACT_VER_MINOR<<8)|(DACT_VER_REVISION);
162 		switch (dc_req&0xff000000) {
163 			case DACT_MOD_REQ_ATLEAST:
164 				if (dact_ver<(dc_req&0xffffff)) {
165 					fprintf(stderr, "%s requires atleast DACT %i.%i.%i, this is DACT %i.%i.%i\n",modulefile,DACT_VER_PARTS(dc_req), DACT_VER_MAJOR, DACT_VER_MINOR, DACT_VER_REVISION);
166 					dlclose(mh);
167 					return(DACT_MOD_FAIL);
168 				}
169 				break;
170 			case DACT_MOD_REQ_EXACTLY:
171 				if ((dc_req&0xffffff)!=dact_ver) {
172 					fprintf(stderr, "%s requires DACT %i.%i.%i, this is DACT %i.%i.%i\n",modulefile, DACT_VER_PARTS(dc_req), DACT_VER_MAJOR, DACT_VER_MINOR, DACT_VER_REVISION);
173 					dlclose(mh);
174 					return(DACT_MOD_FAIL);
175 				}
176 				break;
177 			case DACT_MOD_REQ_ATMOST:
178 				if (dact_ver>(dc_req&0xffffff)) {
179 					fprintf(stderr, "%s requires atmost DACT %i.%i.%i, this is DACT %i.%i.%i\n",modulefile,DACT_VER_PARTS(dc_req), DACT_VER_MAJOR, DACT_VER_MINOR, DACT_VER_REVISION);
180 					dlclose(mh);
181 					return(DACT_MOD_FAIL);
182 				}
183 				break;
184 		}
185 	}
186 
187 
188 
189 	if (modules_count<255) {
190 		modules[modules_count++]=mh;
191 	}
192 
193 	switch (module_type) {
194 		case DACT_MOD_TYPE_COMP:
195 
196 			if (algo_num>=((sizeof(algorithms))/(sizeof(*algorithms)))) return(DACT_MOD_FAIL);
197 			if (algorithms[algo_num]!=DACT_FAILED_ALGO && algorithms[algo_num]!=NULL) {
198 				dlclose(mh);
199 				return(DACT_MOD_FAIL);
200 			}
201 
202 			memcpy(&algorithms[algo_num],dlsym(mh, "DC_ALGO"),sizeof(algorithms[0]));
203 			memcpy(&algorithm_names[algo_num],dlsym(mh,"DC_NAME"),sizeof(algorithm_names[0]));
204 
205 
206 			return(DACT_MOD_OK);
207 		case DACT_MOD_TYPE_ENC:
208 			if (algo_num>=CIPHER_COUNT) {
209 				printf("Encryption algorithm number too high, ignoring %i\n", algo_num);
210 				return(DACT_MOD_FAIL);
211 			}
212 			if (ciphers[algo_num]!=DACT_FAILED_ALGO && ciphers[algo_num]!=NULL) {
213 				return(DACT_MOD_FAIL);
214 			}
215 			memcpy(&ciphers[algo_num],dlsym(mh, "DC_ALGO"),sizeof(algorithms[0]));
216 			memcpy(&ciphers_name[algo_num],dlsym(mh, "DC_NAME"),sizeof(ciphers_name[0]));
217 			return(DACT_MOD_OK);
218 	}
219 	return(DACT_MOD_FAIL);
220 }
221 #else
222 char moduledirectory[2048] = ".";
223 void *modules[256];
224 int modules_initialized = 0;
225 int modules_count = 0;
226 
init_modules(void)227 int init_modules(void) { return(DACT_MOD_FAIL); }
unload_modules(void)228 int unload_modules(void) { return(DACT_MOD_FAIL); }
load_module(char * modulename,const unsigned char * options)229 int load_module(char *modulename, const unsigned char *options) { return(DACT_MOD_FAIL); }
load_modules_all(const unsigned char * options)230 int load_modules_all(const unsigned char *options) { return(DACT_MOD_FAIL); }
231 
232 
233 
234 #endif
235