1 /*
2 * uf_features.c -- part of share.mod
3 *
4 * $Id: uf_features.c,v 1.13 (1.0.3) 2004/05/07 18:55:15 wcc Exp $
5 */
6
7 typedef struct uff_list_struct {
8 struct uff_list_struct *next; /* Pointer to next entry */
9 struct uff_list_struct *prev; /* Pointer to previous entry */
10 uff_table_t *entry;
11 } uff_list_t;
12
13 typedef struct {
14 uff_list_t *start;
15 uff_list_t *end;
16 } uff_head_t;
17
18 static uff_head_t uff_list;
19 static char uff_sbuf[512];
20
uff_init(void)21 static void uff_init(void)
22 {
23 EvangelineBzero(&uff_list, sizeof(uff_head_t));
24 }
25
uff_expmem(void)26 static int uff_expmem(void)
27 {
28 uff_list_t *ul;
29 int tot = 0;
30
31 for (ul = uff_list.start; ul; ul = ul->next)
32 tot += sizeof(uff_list_t);
33 return tot;
34 }
35
36 /* Search for a feature in the uff feature list that matches a supplied
37 * feature flag. Returns a pointer to the entry in the list or NULL if
38 * no feature uses the flag. */
uff_findentry_byflag(int flag)39 static uff_list_t *uff_findentry_byflag(int flag)
40 {
41 uff_list_t *ul;
42
43 for (ul = uff_list.start; ul; ul = ul->next)
44 if (ul->entry->flag & flag)
45 return ul;
46 return NULL;
47 }
48
49 /* Search for a feature in the uff feature list. Returns a pointer to the
50 * entry in the list or NULL if no such feature exists. */
uff_findentry_byname(char * feature)51 static uff_list_t *uff_findentry_byname(char *feature)
52 {
53 uff_list_t *ul;
54
55 for (ul = uff_list.start; ul; ul = ul->next)
56 if (!strcmp(ul->entry->feature, feature))
57 return ul;
58 return NULL;
59 }
60
61 /* Insert entry into sorted list. */
uff_insert_entry(uff_list_t * nul)62 static void uff_insert_entry(uff_list_t *nul)
63 {
64 uff_list_t *ul, *lul = NULL;
65
66 ul = uff_list.start;
67 while (ul && ul->entry->priority < nul->entry->priority) {
68 lul = ul;
69 ul = ul->next;
70 }
71
72 nul->prev = NULL;
73 nul->next = NULL;
74 if (lul) {
75 if (lul->next)
76 lul->next->prev = nul;
77 nul->next = lul->next;
78 nul->prev = lul;
79 lul->next = nul;
80 } else if (ul) {
81 uff_list.start->prev = nul;
82 nul->next = uff_list.start;
83 uff_list.start = nul;
84 } else
85 uff_list.start = nul;
86 if (!nul->next)
87 uff_list.end = nul;
88 }
89
90 /* Remove entry from sorted list. */
uff_remove_entry(uff_list_t * ul)91 static void uff_remove_entry(uff_list_t *ul)
92 {
93 if (!ul->next)
94 uff_list.end = ul->prev;
95 else
96 ul->next->prev = ul->prev;
97 if (!ul->prev)
98 uff_list.start = ul->next;
99 else
100 ul->prev->next = ul->next;
101 }
102
103 /* Add a single feature to the list. */
uff_addfeature(uff_table_t * ut)104 static void uff_addfeature(uff_table_t *ut)
105 {
106 uff_list_t *ul;
107
108 if (uff_findentry_byname(ut->feature)) {
109 putlog(LOG_MISC, "*", "(!) share: same feature name used twice: %s",
110 ut->feature);
111 return;
112 }
113 ul = uff_findentry_byflag(ut->flag);
114 if (ul) {
115 putlog(LOG_MISC, "*", "(!) share: feature flag %d used twice by %s and %s",
116 ut->flag, ut->feature, ul->entry->feature);
117 return;
118 }
119 ul = nmalloc(sizeof(uff_list_t));
120 ul->entry = ut;
121 uff_insert_entry(ul);
122 }
123
124 /* Add a complete table to the list. */
uff_addtable(uff_table_t * ut)125 static void uff_addtable(uff_table_t *ut)
126 {
127 if (!ut)
128 return;
129 for (; ut->feature; ++ut)
130 uff_addfeature(ut);
131 }
132
133 /* Remove a single feature from the list. */
uff_delfeature(uff_table_t * ut)134 static int uff_delfeature(uff_table_t *ut)
135 {
136 uff_list_t *ul;
137
138 for (ul = uff_list.start; ul; ul = ul->next)
139 if (!strcmp(ul->entry->feature, ut->feature)) {
140 uff_remove_entry(ul);
141 nfree(ul);
142 return 1;
143 }
144 return 0;
145 }
146
147 /* Remove a complete table from the list. */
uff_deltable(uff_table_t * ut)148 static void uff_deltable(uff_table_t *ut)
149 {
150 if (!ut)
151 return;
152 for (; ut->feature; ++ut)
153 (int) uff_delfeature(ut);
154 }
155
156 /* Parse the given features string, set internal flags apropriately and
157 * eventually respond with all features we will use. */
uf_features_parse(int idx,char * par)158 static void uf_features_parse(int idx, char *par)
159 {
160 char *buf, *s, *p;
161 uff_list_t *ul;
162
163 uff_sbuf[0] = 0;
164 p = s = buf = nmalloc(strlen(par) + 1);
165 strcpy(buf, par);
166
167 dcc[idx].u.bot->uff_flags = 0;
168
169 while ((s = strchr(s, ' ')) != NULL) {
170 *s = '\0';
171
172 ul = uff_findentry_byname(p);
173 if (ul && (ul->entry->ask_func == NULL || ul->entry->ask_func(idx))) {
174 dcc[idx].u.bot->uff_flags |= ul->entry->flag;
175 strcat(uff_sbuf, ul->entry->feature);
176 strcat(uff_sbuf, " ");
177 if (!strncmp(p, "encrypt", 7)) {
178 encrypt_userfile = 1;
179 debug0("uf_features.c->uf_features_parse) Found 'encrypt' feature, enabling");
180 }
181 }
182 p = ++s;
183 }
184 nfree(buf);
185
186 if (uff_sbuf[0]) {
187 dprintf(idx, "s feats %s\n", uff_sbuf);
188 }
189 }
190
191 /* Return a list of features we are supporting. */
uf_features_dump(int idx)192 static char *uf_features_dump(int idx)
193 {
194 uff_list_t *ul;
195
196 uff_sbuf[0] = 0;
197 for (ul = uff_list.start; ul; ul = ul->next)
198 if (ul->entry->ask_func == NULL || ul->entry->ask_func(idx)) {
199 strcat(uff_sbuf, ul->entry->feature);
200 strcat(uff_sbuf, " ");
201 }
202 return uff_sbuf;
203 }
204
uf_features_check(int idx,char * par)205 static int uf_features_check(int idx, char *par)
206 {
207 char *buf, *s, *p;
208 uff_list_t *ul;
209
210 uff_sbuf[0] = 0;
211 p = s = buf = nmalloc(strlen(par) + 1);
212 strcpy(buf, par);
213
214 dcc[idx].u.bot->uff_flags = 0;
215
216 while ((s = strchr(s, ' ')) != NULL) {
217 *s = '\0';
218
219 ul = uff_findentry_byname(p);
220 if (ul && (ul->entry->ask_func == NULL || ul->entry->ask_func(idx))) {
221 dcc[idx].u.bot->uff_flags |= ul->entry->flag;
222 } else {
223 putlog(LOG_BOTS, "*", "Bot %s tried unsupported feature!", dcc[idx].nick);
224 dprintf(idx, "s e Attempt to use an unsupported feature\n");
225 zapfbot(idx);
226
227 nfree(buf);
228 return 0;
229 }
230 p = ++s;
231 }
232 nfree(buf);
233 return 1;
234 }
235
236 /* Call all active feature functions, sorted by their priority. This
237 * should be called when we're about to send a user file. */
uff_call_sending(int idx,char * user_file)238 static int uff_call_sending(int idx, char *user_file)
239 {
240 uff_list_t *ul;
241
242 for (ul = uff_list.start; ul; ul = ul->next)
243 if (ul->entry && ul->entry->snd &&
244 (dcc[idx].u.bot->uff_flags & ul->entry->flag))
245 if (!(ul->entry->snd(idx, user_file)))
246 return 0;
247 return 1;
248 }
249
250 /* Call all active feature functions, sorted by their priority. This
251 * should be called when we've received a user file and are about to
252 * parse it. */
uff_call_receiving(int idx,char * user_file)253 static int uff_call_receiving(int idx, char *user_file)
254 {
255 uff_list_t *ul;
256
257 for (ul = uff_list.end; ul; ul = ul->prev)
258 if (ul->entry && ul->entry->rcv &&
259 (dcc[idx].u.bot->uff_flags & ul->entry->flag))
260 if (!(ul->entry->rcv(idx, user_file)))
261 return 0;
262 return 1;
263 }
264
265 /* Feature `overbots' */
uff_ask_override_bots(int idx)266 static int uff_ask_override_bots(int idx)
267 {
268 if (overr_local_bots)
269 return 1;
270 else
271 return 0;
272 }
273
274 /* Feature `compress` */
275 #ifndef ZLIB_PROBLEM
276 int compress_level = 9;
277
uff_comp(int idx,char * filename)278 static int uff_comp(int idx, char *filename)
279 {
280 debug1("(uf_features.c->uff_comp) Compressing user file for %s. (zlib)", dcc[idx].nick);
281 return compress_file(filename, compress_level);
282 }
283
uff_uncomp(int idx,char * filename)284 static int uff_uncomp(int idx, char *filename)
285 {
286 debug1("(uf_features.c->uff_uncomp) Uncompressing user file from %s. (zlib)", dcc[idx].nick);
287 return uncompress_file(filename);
288 }
289
uff_ask_compress(int idx)290 static int uff_ask_compress(int idx)
291 {
292 if (share_compressed)
293 return 1;
294 else
295 return 0;
296 }
297 #endif
298
299 /* Feature `encrypt` */
300 static int uff_writeenc(int idx, char *fname);
301 static int uff_readenc(int idx, char *fname);
302 static int is_encryptedfile(char *fname);
303
share_cryptKey(int idx,char * par)304 static void share_cryptKey(int idx, char *par) {
305 char *ki;
306 ki = newsplit(&par);
307 debug2("(uf_features.c->share_cryptKey) Got shareKey from %s: %s", dcc[idx].nick, ki);
308 strcpy(shareKey, ki);
309 }
310
share_md5sum(int idx,char * par)311 static void share_md5sum(int idx, char *par) {
312 char *ki;
313 ki = newsplit(&par);
314 debug2("(uf_features.c->share_md5sum) Got md5sum from %s: %s", dcc[idx].nick, ki);
315 strcpy(md5sum, ki);
316 }
317
is_encryptedfile(char * fname)318 static int is_encryptedfile(char *fname) {
319 FILE *file;
320 char buffer[512];
321
322 file = fopen(fname, "r");
323 if (file == NULL)
324 return 0;
325 fgets(buffer, 511, file);
326 if (!strncmp(buffer, "#Evangeline!Encrypted: Userfile", 31))
327 return 1;
328 else
329 return 0;
330 }
331
uff_writeenc(int idx,char * fname)332 static int uff_writeenc(int idx, char *fname) {
333
334 debug2("(uf_features.c->uff_writeenc) Sending shareKey to %s: %s", dcc[idx].nick, shareKey);
335 dprintf(idx, "s sck %s\n", shareKey);
336 putlog(LOG_BOTS, "*", "Encrypting userfile for %s", dcc[idx].nick);
337
338 return 1;
339 }
340
uff_readenc(int idx,char * fname)341 static int uff_readenc(int idx, char *fname) {
342
343 if (is_encryptedfile(fname)) {
344 encrypt_userfile = 1;
345 putlog(LOG_BOTS, "*", "Decrypting userfile from %s", dcc[idx].nick);
346 }
347 return 1;
348 }
349
uff_ask_sharecrypt(int idx)350 static int uff_ask_sharecrypt(int idx) {
351 if (share_encrypted)
352 return 1;
353 else
354 return 0;
355 }
356
357 static uff_table_t internal_uff_table[] = {
358 {"overbots", UFF_OVERRIDE, uff_ask_override_bots, 0, NULL, NULL},
359 {"invites", UFF_INVITE, NULL, 0, NULL, NULL},
360 {"exempts", UFF_EXEMPT, NULL, 0, NULL, NULL},
361 #ifndef ZLIB_PROBLEM
362 {"compress", UFF_COMPRESS, uff_ask_compress, 100, uff_comp, uff_uncomp},
363 #endif
364 {"encrypt", UFF_ENCRYPT, uff_ask_sharecrypt, 100, uff_writeenc, uff_readenc},
365 {NULL, 0, NULL, 0, NULL, NULL}
366 };
367