- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / oscam-config-account.c
blob351a91041112544ef173ff3655de922e660eecde
1 #define MODULE_LOG_PREFIX "config"
3 #include "globals.h"
4 #include "module-anticasc.h"
5 #include "oscam-array.h"
6 #include "oscam-client.h"
7 #include "oscam-conf.h"
8 #include "oscam-conf-chk.h"
9 #include "oscam-conf-mk.h"
10 #include "oscam-config.h"
11 #include "oscam-garbage.h"
12 #include "oscam-lock.h"
13 #include "oscam-string.h"
14 #ifdef CS_CACHEEX_AIO
15 #include "module-cacheex.h"
16 #endif
17 #define cs_user "oscam.user"
19 static void account_tosleep_fn(const char *token, char *value, void *setting, FILE *f)
21 int32_t *tosleep = setting;
22 if(value)
24 *tosleep = strToIntVal(value, cfg.tosleep);
25 return;
27 if(*tosleep != cfg.tosleep || cfg.http_full_cfg)
28 { fprintf_conf(f, token, "%d\n", *tosleep); }
31 static void account_c35_suppresscmd08_fn(const char *token, char *value, void *setting, FILE *f)
33 int8_t *c35_suppresscmd08 = setting;
34 if(value)
36 *c35_suppresscmd08 = (int8_t)strToIntVal(value, cfg.c35_suppresscmd08);
37 return;
39 if(*c35_suppresscmd08 != cfg.c35_suppresscmd08 || cfg.http_full_cfg)
40 { fprintf_conf(f, token, "%d\n", *c35_suppresscmd08); }
43 /*static void account_umaxidle_fn(const char *token, char *value, void *setting, FILE *f)
45 int32_t *umaxidle = setting;
46 if(value)
48 *umaxidle = (int32_t)strToIntVal(value, cfg.umaxidle);
49 return;
51 if(*umaxidle != cfg.umaxidle || cfg.http_full_cfg)
52 { fprintf_conf(f, token, "%u\n", *umaxidle); }
56 static void account_ncd_keepalive_fn(const char *token, char *value, void *setting, FILE *f)
58 int8_t *ncd_keepalive = setting;
59 int8_t def_value = 0;
60 #ifdef MODULE_NEWCAMD
61 def_value = cfg.ncd_keepalive;
62 #endif
63 if(value)
65 *ncd_keepalive = (int8_t)strToIntVal(value, def_value);
66 return;
68 if(*ncd_keepalive != def_value || cfg.http_full_cfg)
69 { fprintf_conf(f, token, "%d\n", *ncd_keepalive); }
72 static void account_allowedprotocols_fn(const char *token, char *value, void *setting, FILE *f)
74 struct s_auth *account = setting;
75 if(value)
77 account->allowedprotocols = 0;
78 if(cs_strlen(value) > 3)
80 int i;
81 char *ptr, *saveptr1 = NULL;
82 for(i = 0, ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1), i++)
84 if(streq(ptr, "camd33")) { account->allowedprotocols |= LIS_CAMD33TCP; }
85 else if(streq(ptr, "camd35")) { account->allowedprotocols |= LIS_CAMD35UDP; }
86 else if(streq(ptr, "cs357x")) { account->allowedprotocols |= LIS_CAMD35UDP; }
87 else if(streq(ptr, "cs378x")) { account->allowedprotocols |= LIS_CAMD35TCP; }
88 else if(streq(ptr, "newcamd")) { account->allowedprotocols |= LIS_NEWCAMD; }
89 else if(streq(ptr, "cccam")) { account->allowedprotocols |= LIS_CCCAM; }
90 else if(streq(ptr, "csp")) { account->allowedprotocols |= LIS_CSPUDP; }
91 else if(streq(ptr, "gbox")) { account->allowedprotocols |= LIS_GBOX; }
92 else if(streq(ptr, "radegast")) { account->allowedprotocols |= LIS_RADEGAST; }
93 else if(streq(ptr, "scam")) { account->allowedprotocols |= LIS_SCAM; }
94 // these have no listener ports so it doesn't make sense
95 else if(streq(ptr, "dvbapi")) { account->allowedprotocols |= LIS_DVBAPI; }
96 else if(streq(ptr, "constcw")) { account->allowedprotocols |= LIS_CONSTCW; }
97 else if(streq(ptr, "serial")) { account->allowedprotocols |= LIS_SERIAL; }
100 return;
102 if(account->allowedprotocols || cfg.http_full_cfg)
104 value = mk_t_allowedprotocols(account);
105 fprintf_conf(f, token, "%s\n", value);
106 free_mk_t(value);
110 static void account_au_fn(const char *token, char *value, void *setting, FILE *f)
112 struct s_auth *account = setting;
113 if(value)
115 // set default values for usage during runtime from Webif
116 account->autoau = 0;
117 if(!account->aureader_list)
118 { account->aureader_list = ll_create("aureader_list"); }
119 if(streq(value, "1"))
120 { account->autoau = 1; }
121 ll_clear(account->aureader_list);
122 LL_ITER itr = ll_iter_create(configured_readers);
123 struct s_reader *rdr;
124 char *pch, *saveptr1 = NULL;
125 for(pch = strtok_r(value, ",", &saveptr1); pch != NULL; pch = strtok_r(NULL, ",", &saveptr1))
127 ll_iter_reset(&itr);
128 while((rdr = ll_iter_next(&itr)))
130 if(streq(rdr->label, pch) || account->autoau)
132 ll_append(account->aureader_list, rdr);
136 return;
138 if(account->autoau == 1)
140 fprintf_conf(f, token, "%d\n", account->autoau);
142 else if(account->aureader_list)
144 value = mk_t_aureader(account);
145 if(cs_strlen(value) > 0)
146 { fprintf_conf(f, token, "%s\n", value); }
147 free_mk_t(value);
149 else if(cfg.http_full_cfg)
151 fprintf_conf(f, token, "%s\n", "");
155 static void account_expdate_fn(const char *token, char *value, void *setting, FILE *f)
157 struct s_auth *account = setting;
158 if(value)
160 if(!value[0])
162 account->expirationdate = (time_t)NULL;
163 return;
165 int i;
166 struct tm cstime;
167 char *ptr1, *saveptr1 = NULL;
168 memset(&cstime, 0, sizeof(cstime));
169 for(i = 0, ptr1 = strtok_r(value, "-/", &saveptr1); i < 3 && ptr1; ptr1 = strtok_r(NULL, "-/", &saveptr1), i++)
171 switch(i)
173 case 0:
174 cstime.tm_year = atoi(ptr1) - 1900;
175 break;
176 case 1:
177 cstime.tm_mon = atoi(ptr1) - 1;
178 break;
179 case 2:
180 cstime.tm_mday = atoi(ptr1);
181 break;
184 cstime.tm_hour = 23;
185 cstime.tm_min = 59;
186 cstime.tm_sec = 59;
187 cstime.tm_isdst = -1;
188 account->expirationdate = mktime(&cstime);
189 return;
191 if(account->expirationdate || cfg.http_full_cfg)
193 char buf[16];
194 struct tm timeinfo;
195 localtime_r(&account->expirationdate, &timeinfo);
196 strftime(buf, 16, "%Y-%m-%d", &timeinfo);
197 fprintf_conf(f, token, "%s\n", streq(buf, "1970-01-01") ? "" : buf);
201 static void account_allowedtimeframe_fn(const char *token, char *value, void *setting, FILE *f)
203 struct s_auth *account = setting;
204 int32_t i, j, t, startt, endt;
205 char *dest;
206 uint8_t day_idx;
207 int32_t allowed[4];
208 uint32_t tempo = 0;
210 char *ptr1, *ptr2, *ptr3, *saveptr1 = NULL, *saveptr2 = NULL;
212 if(value)
214 //First empty allowedtimeframe array very important otherwise new config won't be properly set
215 for(i = 0; i < SIZE_SHORTDAY; i++)
217 for(j = 0; j < 24; j++)
219 account->allowedtimeframe[i][j][0] = 0;
220 account->allowedtimeframe[i][j][1] = 0;
223 account->allowedtimeframe_set=0;
224 strtoupper(value);
226 for(i = 0, ptr1 = strtok_r(value, ";", &saveptr1); (ptr1); ptr1 = strtok_r(NULL, ";", &saveptr1), i++)
228 if((ptr2 = strchr(trim(ptr1), '@')))
230 *ptr2++ = '\0'; // clean up @ symbol
231 // ptr1 is the day
232 dest = strstr(weekdstr,ptr1);
233 day_idx = (dest - weekdstr) / 3;
235 for(j = 0, ptr3 = strtok_r(ptr2, ",", &saveptr2); (ptr3); ptr3 = strtok_r(NULL, ",", &saveptr2), j++)
237 if((sscanf(ptr3, "%2d:%2d-%2d:%2d", &allowed[0], &allowed[1], &allowed[2], &allowed[3]) == 4) && (day_idx < SIZE_SHORTDAY))
239 startt = allowed[0] * 60 + allowed[1];
240 endt = allowed[2] * 60 + allowed[3];
242 if(startt == endt) { endt++; } // end time cannot be the same as the star time
243 if((startt < 0) || (startt > 1439)) { startt = 0; } // could not start later than 23H59, avoid overflow
244 if((endt < 0) || (endt > 1440)) { endt = 1440; } // could not be higher than 24H00, avoid overflow
246 account->allowedtimeframe_set = 1;
248 if(startt > endt)
250 for(t = startt; t < 1440; t++)
252 tempo = (1 << (t % 30));
253 account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] = account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] | tempo;
255 startt = 0;
258 for(t = startt; t < endt; t++)
260 tempo = (1 << (t % 30));
261 account->allowedtimeframe[day_idx][t / 60][((t / 30) % 2)] = account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] | tempo;
264 else
266 fprintf(stderr, "WARNING: Value '%s' is not valid for allowedtimeframe (DAY@HH:MM-HH:MM)\n", value);
270 else // No day specified so whole week (ALL)
272 if(sscanf(ptr1, "%2d:%2d-%2d:%2d", &allowed[0], &allowed[1], &allowed[2], &allowed[3]) == 4)
274 startt = allowed[0] * 60 + allowed[1];
275 endt = allowed[2] * 60 + allowed[3];
277 if(startt == endt) { endt++; } // end time cannot be the same as the star time
278 if((startt <0) || (startt > 1439)) { startt = 0; } // could not start later than 23H59, avoid overflow
279 if((endt <0) || (endt > 1440)) { endt = 1440; } // could not be higher than 24H00, avoid overflow
281 account->allowedtimeframe_set = 1;
282 dest = strstr(weekdstr,"ALL");
283 day_idx = (dest - weekdstr) / 3;
285 if(startt > endt)
287 for(t = startt; t < 1440; t++)
289 tempo = (1 << (t % 30));
290 account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] = account->allowedtimeframe[7][t / 60][(t / 30) % 2] | tempo;
292 startt=0;
295 for(t = startt; t < endt; t++)
297 tempo = (1 << (t % 30));
298 account->allowedtimeframe[day_idx][t / 60][(t / 30) % 2] = account->allowedtimeframe[7][t / 60][(t / 30) % 2] | tempo;
301 else
303 fprintf(stderr, "WARNING: Value '%s' is not valid for allowedtimeframe (hh:mm-hh:mm)\n", value);
308 return;
310 if(account->allowedtimeframe_set)
312 value = mk_t_allowedtimeframe(account);
313 fprintf_conf(f, token, "%s\n", value);
314 free_mk_t(value);
316 else if(cfg.http_full_cfg)
318 fprintf_conf(f, token, "%s\n", "");
322 static void account_tuntab_fn(const char *token, char *value, void *setting, FILE *f)
324 TUNTAB *ttab = setting;
325 if(value)
327 if(cs_strlen(value) == 0)
329 tuntab_clear(ttab);
331 else
333 chk_tuntab(value, ttab);
335 return;
337 if((ttab->ttdata && ttab->ttdata[0].bt_caidfrom) || cfg.http_full_cfg)
339 value = mk_t_tuntab(ttab);
340 fprintf_conf(f, token, "%s\n", value);
341 free_mk_t(value);
345 void group_fn(const char *token, char *value, void *setting, FILE *f)
347 uint64_t *grp = setting;
348 if(value)
350 char *ptr1, *saveptr1 = NULL;
351 *grp = 0;
352 for(ptr1 = strtok_r(value, ",", &saveptr1); ptr1; ptr1 = strtok_r(NULL, ",", &saveptr1))
354 int32_t g;
355 g = atoi(ptr1);
356 if(g > 0 && g < 65)
357 { *grp |= (((uint64_t)1) << (g - 1)); }
359 return;
361 if(*grp || cfg.http_full_cfg)
363 value = mk_t_group(*grp);
364 fprintf_conf(f, token, "%s\n", value);
365 free_mk_t(value);
369 void services_fn(const char *token, char *value, void *setting, FILE *f)
371 SIDTABS *sidtabs = setting;
372 if(value)
374 strtolower(value);
375 chk_services(value, sidtabs);
376 return;
378 value = mk_t_service(sidtabs);
379 if(cs_strlen(value) > 0 || cfg.http_full_cfg)
380 { fprintf_conf(f, token, "%s\n", value); }
381 free_mk_t(value);
384 void class_fn(const char *token, char *value, void *setting, FILE *f)
386 CLASSTAB *cltab = setting;
387 if(value)
389 strtolower(value);
390 chk_cltab(value, cltab);
391 return;
393 value = mk_t_cltab(cltab);
394 if(cs_strlen(value) > 0 || cfg.http_full_cfg)
396 fprintf_conf(f, token, "%s\n", value);
397 free_mk_t(value);
401 #if defined(CS_ANTICASC) || defined(CS_CACHEEX_AIO)
402 static void account_fixups_fn(void *var)
404 struct s_auth *account = var;
405 #endif
406 #if defined(CS_ANTICASC)
407 if(account->ac_users < -1) { account->ac_users = DEFAULT_AC_USERS; }
408 if(account->ac_penalty < -1) { account->ac_penalty = DEFAULT_AC_PENALTY; }
409 if(account->acosc_max_ecms_per_minute < -1) { account->acosc_max_ecms_per_minute = -1; }
410 if(account->acosc_max_active_sids < -1) { account->acosc_max_active_sids = -1; }
411 if(account->acosc_zap_limit < -1) { account->acosc_zap_limit = -1; }
412 if(account->acosc_penalty < -1) { account->acosc_penalty = -1; }
413 if(account->acosc_penalty_duration < -1) { account->acosc_penalty_duration = -1; }
414 if(account->acosc_delay < -1) { account->acosc_delay = -1; }
415 if((account->acosc_penalty == 4) || ((cfg.acosc_penalty == 4) && (account->acosc_penalty == -1)))
417 account->acosc_max_active_sids = -1; // use global value
418 account->acosc_zap_limit = -1; // use global value
419 account->acosc_penalty_duration = -1; // use global value
421 if((account->acosc_max_ecms_per_minute != -1) && (account->acosc_max_ecms_per_minute != 0))
423 if(account->acosc_max_ecms_per_minute < 6) { account->acosc_max_ecms_per_minute = 6; }
424 if(account->acosc_max_ecms_per_minute > 20) { account->acosc_max_ecms_per_minute = 20; }
425 account->acosc_penalty_duration = (60 / account->acosc_max_ecms_per_minute);
428 #endif
429 #if defined(CS_CACHEEX_AIO)
430 // lgo-ctab -> lgo-ftab port
431 caidtab2ftab_add(&account->cacheex.localgenerated_only_in_caidtab, &account->cacheex.lg_only_in_tab);
432 caidtab_clear(&account->cacheex.localgenerated_only_in_caidtab);
433 caidtab2ftab_add(&account->cacheex.localgenerated_only_caidtab, &account->cacheex.lg_only_tab);
434 caidtab_clear(&account->cacheex.localgenerated_only_caidtab);
435 #endif
436 #if defined(CS_ANTICASC) || defined(CS_CACHEEX_AIO)
438 #endif
440 #define OFS(X) offsetof(struct s_auth, X)
441 #define SIZEOF(X) sizeof(((struct s_auth *)0)->X)
443 static const struct config_list account_opts[] =
445 #if defined(CS_ANTICASC) || defined(CS_CACHEEX_AIO)
446 DEF_OPT_FIXUP_FUNC(account_fixups_fn),
447 #endif
448 DEF_OPT_INT8("disabled" , OFS(disabled), 0),
449 DEF_OPT_SSTR("user" , OFS(usr), "", SIZEOF(usr)),
450 DEF_OPT_STR("pwd" , OFS(pwd), NULL),
451 #ifdef WEBIF
452 DEF_OPT_STR("description" , OFS(description), NULL),
453 #endif
454 DEF_OPT_STR("hostname" , OFS(dyndns), NULL),
455 DEF_OPT_FUNC("caid" , OFS(ctab), check_caidtab_fn),
456 DEF_OPT_INT8("uniq" , OFS(uniq), 0),
457 DEF_OPT_UINT8("sleepsend" , OFS(c35_sleepsend), 0),
458 DEF_OPT_INT32("failban" , OFS(failban), 0),
459 DEF_OPT_INT8("monlevel" , OFS(monlvl), 0),
460 DEF_OPT_FUNC("sleep" , OFS(tosleep), account_tosleep_fn),
461 DEF_OPT_FUNC("suppresscmd08" , OFS(c35_suppresscmd08), account_c35_suppresscmd08_fn),
462 DEF_OPT_INT32("umaxidle" , OFS(umaxidle), -1),
463 DEF_OPT_FUNC("keepalive" , OFS(ncd_keepalive), account_ncd_keepalive_fn),
464 DEF_OPT_FUNC("au" , 0, account_au_fn),
465 DEF_OPT_UINT8("emmreassembly" , OFS(emm_reassembly), 2),
466 DEF_OPT_FUNC("expdate" , 0, account_expdate_fn),
467 DEF_OPT_FUNC("allowedprotocols" , 0, account_allowedprotocols_fn),
468 DEF_OPT_FUNC("allowedtimeframe" , 0, account_allowedtimeframe_fn),
469 DEF_OPT_FUNC("betatunnel" , OFS(ttab), account_tuntab_fn),
470 DEF_OPT_FUNC("group" , OFS(grp), group_fn),
471 DEF_OPT_FUNC("services" , OFS(sidtabs), services_fn),
472 DEF_OPT_INT8("preferlocalcards" , OFS(preferlocalcards), -1),
473 DEF_OPT_FUNC_X("ident" , OFS(ftab), ftab_fn, FTAB_ACCOUNT | FTAB_PROVID),
474 DEF_OPT_FUNC_X("chid" , OFS(fchid), ftab_fn, FTAB_ACCOUNT | FTAB_CHID),
475 DEF_OPT_FUNC("class" , OFS(cltab), class_fn),
476 DEF_OPT_UINT32("max_connections" , OFS(max_connections), 1),
477 #ifdef CS_CACHEEX
478 DEF_OPT_INT8("cacheex" , OFS(cacheex.mode), 0),
479 DEF_OPT_INT8("cacheex_maxhop" , OFS(cacheex.maxhop), 0),
480 #ifdef CS_CACHEEX_AIO
481 DEF_OPT_INT8("cacheex_maxhop_lg" , OFS(cacheex.maxhop_lg), 0),
482 #endif
483 DEF_OPT_FUNC("cacheex_ecm_filter" , OFS(cacheex.filter_caidtab), cacheex_hitvaluetab_fn),
484 DEF_OPT_UINT8("cacheex_drop_csp" , OFS(cacheex.drop_csp), 0),
485 DEF_OPT_UINT8("cacheex_allow_request" , OFS(cacheex.allow_request), 0),
486 DEF_OPT_UINT8("no_wait_time" , OFS(no_wait_time), 0),
487 DEF_OPT_UINT8("cacheex_allow_filter" , OFS(cacheex.allow_filter), 1),
488 #ifdef CS_CACHEEX_AIO
489 DEF_OPT_UINT8("cacheex_allow_maxhop" , OFS(cacheex.allow_maxhop), 0),
490 #endif
491 DEF_OPT_UINT8("cacheex_block_fakecws" , OFS(cacheex.block_fakecws), 0),
492 DEF_OPT_UINT8("disablecrccacheex" , OFS(disablecrccacheex), 0),
493 DEF_OPT_FUNC_X("disablecrccacheex_only_for", OFS(disablecrccacheex_only_for), ftab_fn, FTAB_ACCOUNT | FTAB_IGNCRCCEX4USERONLYFOR),
494 #ifdef CS_CACHEEX_AIO
495 DEF_OPT_UINT8("cacheex_cw_check_for_push" , OFS(cacheex.cw_check_for_push), 0),
496 DEF_OPT_UINT8("cacheex_lg_only_remote_settings", OFS(cacheex.lg_only_remote_settings), 1),
497 DEF_OPT_UINT8("cacheex_localgenerated_only", OFS(cacheex.localgenerated_only), 0),
498 DEF_OPT_FUNC("cacheex_localgenerated_only_caid", OFS(cacheex.localgenerated_only_caidtab), check_caidtab_fn),
499 DEF_OPT_FUNC_X("cacheex_lg_only_tab" , OFS(cacheex.lg_only_tab), ftab_fn, 0),
500 DEF_OPT_UINT8("cacheex_lg_only_in_aio_only", OFS(cacheex.lg_only_in_aio_only), 0),
501 DEF_OPT_UINT8("cacheex_localgenerated_only_in", OFS(cacheex.localgenerated_only_in), 0),
502 DEF_OPT_FUNC("cacheex_localgenerated_only_in_caid", OFS(cacheex.localgenerated_only_in_caidtab), check_caidtab_fn),
503 DEF_OPT_FUNC_X("cacheex_lg_only_in_tab" , OFS(cacheex.lg_only_in_tab), ftab_fn, 0),
504 DEF_OPT_FUNC("cacheex_nopushafter" , OFS(cacheex.cacheex_nopushafter_tab), caidvaluetab_fn),
505 #endif
506 #endif
507 #ifdef MODULE_CCCAM
508 DEF_OPT_INT32("cccmaxhops" , OFS(cccmaxhops), DEFAULT_CC_MAXHOPS),
509 DEF_OPT_INT8("cccreshare" , OFS(cccreshare), DEFAULT_CC_RESHARE),
510 DEF_OPT_INT8("cccignorereshare" , OFS(cccignorereshare), DEFAULT_CC_IGNRSHR),
511 DEF_OPT_INT8("cccstealth" , OFS(cccstealth), DEFAULT_CC_STEALTH),
512 #endif
513 #ifdef CS_ANTICASC
514 DEF_OPT_INT32("fakedelay" , OFS(ac_fakedelay), -1),
515 DEF_OPT_INT32("numusers" , OFS(ac_users), DEFAULT_AC_USERS),
516 DEF_OPT_INT8("penalty" , OFS(ac_penalty), DEFAULT_AC_PENALTY),
517 DEF_OPT_INT8("acosc_max_ecms_per_minute" , OFS(acosc_max_ecms_per_minute), -1 ),
518 DEF_OPT_INT8("acosc_max_active_sids" , OFS(acosc_max_active_sids), -1 ),
519 DEF_OPT_INT8("acosc_zap_limit" , OFS(acosc_zap_limit), -1 ),
520 DEF_OPT_INT8("acosc_penalty" , OFS(acosc_penalty), -1 ),
521 DEF_OPT_INT32("acosc_penalty_duration" , OFS(acosc_penalty_duration), -1 ),
522 DEF_OPT_INT32("acosc_delay" , OFS(acosc_delay), -1 ),
523 #endif
524 #ifdef WITH_LB
525 DEF_OPT_INT32("lb_nbest_readers" , OFS(lb_nbest_readers), -1),
526 DEF_OPT_INT32("lb_nfb_readers" , OFS(lb_nfb_readers), -1),
527 DEF_OPT_FUNC("lb_nbest_percaid" , OFS(lb_nbest_readers_tab), caidvaluetab_fn),
528 #endif
529 #ifdef CW_CYCLE_CHECK
530 DEF_OPT_INT8("cwc_disable" , OFS(cwc_disable), 0),
531 #endif
532 DEF_LAST_OPT
535 void chk_account(const char *token, char *value, struct s_auth *account)
537 if(config_list_parse(account_opts, token, value, account))
538 { return; }
539 else if(token[0] != '#')
540 { fprintf(stderr, "Warning: keyword '%s' in account section not recognized\n", token); }
543 void account_set_defaults(struct s_auth *account)
545 config_list_set_defaults(account_opts, account);
548 struct s_auth *init_userdb(void)
550 FILE *fp = open_config_file(cs_user);
551 if(!fp)
552 { return NULL; }
554 struct s_auth *authptr = NULL;
555 int32_t tag = 0, nr = 0, expired = 0, disabled = 0;
556 char *token;
557 struct s_auth *account = NULL;
558 struct s_auth *probe = NULL;
559 if(!cs_malloc(&token, MAXLINESIZE))
560 { return NULL; }
562 while(fgets(token, MAXLINESIZE, fp))
564 int32_t l;
565 void *ptr;
567 if((l = cs_strlen(trim(token))) < 3)
568 { continue; }
569 if(token[0] == '[' && token[l - 1] == ']')
571 token[l - 1] = 0;
572 tag = streq("account", strtolower(token + 1));
573 if(!cs_malloc(&ptr, sizeof(struct s_auth)))
574 { break; }
575 if(account)
576 { account->next = ptr; }
577 else
578 { authptr = ptr; }
580 account = ptr;
581 account_set_defaults(account);
582 nr++;
584 continue;
587 if(!tag)
588 { continue; }
589 char *value = strchr(token, '=');
590 if(!value)
591 { continue; }
593 *value++ = '\0';
595 // check for duplicate useraccounts and make the name unique
596 if(streq(trim(strtolower(token)), "user"))
598 for(probe = authptr; probe; probe = probe->next)
600 if(!strcmp(probe->usr, trim(value)))
602 fprintf(stderr, "Warning: duplicate account '%s'\n", value);
603 if (!cs_strncat(value, "_x", sizeof(probe->usr))) {
604 cs_log("WARNING, bug here!");
609 chk_account(trim(strtolower(token)), trim(value), account);
611 NULLFREE(token);
612 fclose(fp);
614 for(account = authptr; account; account = account->next)
616 if(account->expirationdate && account->expirationdate < time(NULL))
617 { ++expired; }
618 if(account->disabled)
619 { ++disabled; }
621 cs_log("userdb reloaded: %d accounts loaded, %d expired, %d disabled", nr, expired, disabled);
622 return authptr;
625 int32_t init_free_userdb(struct s_auth *ptr)
627 int32_t nro;
628 for(nro = 0; ptr; nro++)
630 struct s_auth *ptr_next;
631 ptr_next = ptr->next;
632 ll_destroy(&ptr->aureader_list);
633 ptr->next = NULL;
634 config_list_gc_values(account_opts, ptr);
635 ftab_clear(&ptr->ftab);
636 ftab_clear(&ptr->fchid);
637 tuntab_clear(&ptr->ttab);
638 caidtab_clear(&ptr->ctab);
639 NULLFREE(ptr->cltab.aclass);
640 NULLFREE(ptr->cltab.bclass);
641 #ifdef CS_CACHEEX
642 cecspvaluetab_clear(&ptr->cacheex.filter_caidtab);
643 ftab_clear(&ptr->disablecrccacheex_only_for);
644 #ifdef CS_CACHEEX_AIO
645 caidtab_clear(&ptr->cacheex.localgenerated_only_caidtab);
646 caidtab_clear(&ptr->cacheex.localgenerated_only_in_caidtab);
647 ftab_clear(&ptr->cacheex.lg_only_tab);
648 ftab_clear(&ptr->cacheex.lg_only_in_tab);
649 caidvaluetab_clear(&ptr->cacheex.cacheex_nopushafter_tab);
650 #endif
651 #endif
652 #ifdef WITH_LB
653 caidvaluetab_clear(&ptr->lb_nbest_readers_tab);
654 #endif
655 add_garbage(ptr);
656 ptr = ptr_next;
658 cs_log("userdb %d accounts freed", nro);
659 return nro;
662 int32_t write_userdb(void)
664 struct s_auth *account;
665 FILE *f = create_config_file(cs_user);
666 if(!f)
667 { return 1; }
668 for(account = cfg.account; account; account = account->next)
670 fprintf(f, "[account]\n");
671 config_list_apply_fixups(account_opts, account);
672 config_list_save(f, account_opts, account, cfg.http_full_cfg);
673 fprintf(f, "\n");
675 return flush_config_file(f, cs_user);
678 void cs_accounts_chk(void)
680 struct s_auth *account1, *account2;
681 struct s_auth *new_accounts = init_userdb();
682 cs_writelock(__func__, &config_lock);
683 struct s_auth *old_accounts = cfg.account;
684 for(account1 = cfg.account; account1; account1 = account1->next)
686 for(account2 = new_accounts; account2; account2 = account2->next)
688 if(!strcmp(account1->usr, account2->usr))
690 account2->cwfound = account1->cwfound;
691 account2->cwcache = account1->cwcache;
692 account2->cwnot = account1->cwnot;
693 account2->cwtun = account1->cwtun;
694 account2->cwignored = account1->cwignored;
695 account2->cwtout = account1->cwtout;
696 account2->emmok = account1->emmok;
697 account2->emmnok = account1->emmnok;
698 account2->firstlogin = account1->firstlogin;
699 ac_copy_vars(account1, account2);
703 cs_reinit_clients(new_accounts);
704 cfg.account = new_accounts;
705 init_free_userdb(old_accounts);
706 ac_clear();
707 cs_writeunlock(__func__, &config_lock);