static void cf_load_functions(void) { cf_function_t *function; var_t *v; void *data; for(function = cf_functions; function->cf_type; ++function) { if(vtable_get(cf_config, function->cf_name)) { continue; } function->cf_callback(&data); if (data == NULL) { log_die(EX_CONFIG, "cf_load_functions: callback for " "\"%s\" failed", function->cf_name); } v = var_create(function->cf_type, function->cf_name, data, VF_KEEPNAME); if (v == NULL) { log_die(EX_CONFIG, "cf_load_functions: var_create " "failed"); } if(vtable_set(cf_config, v) == -1) { log_die(EX_CONFIG, "cf_load_functions: var_table_set " "failed"); } } return; }
void watchdog_close(var_t *table) { char *id; if (pthread_mutex_lock(&watchdog_mutex)) { log_sys_error("watchdog_remove: pthread_mutex_lock"); goto exit; } id = vtable_get(table, "id"); if (id == NULL) { log_error("watchdog_remove: vtable_get returned no id"); goto exit; } sht_remove(&watchdog_table, id); exit: if (pthread_mutex_unlock(&watchdog_mutex)) { log_sys_error("watchdog_remove: pthread_mutex_unlock"); } return; }
void watchdog(var_t *table, char *stage) { watchdog_t *wd; char *id; if (pthread_mutex_lock(&watchdog_mutex)) { log_sys_error("watchdog: pthread_mutex_lock"); return; } watchdog_init(); // In init id is not set. No problem. id = vtable_get(table, "id"); if (id == NULL) { goto exit; } // Record does not exist wd = sht_lookup(&watchdog_table, id); if (wd == NULL) { wd = watchdog_create(id, stage); if (wd == NULL) { log_error("watchdog: watchdog_create failed"); goto exit; } if (sht_insert(&watchdog_table, id, wd)) { log_error("watchdog: sht_insert failed"); goto exit; } } else { wd->wd_stage = stage; wd->wd_instage = time(NULL); } exit: if (pthread_mutex_unlock(&watchdog_mutex)) { log_sys_error("watchdog: pthread_mutex_unlock"); } return; }
static var_t * exp_eval_macro(exp_t *exp, var_t *mailspec) { VAR_INT_T *stage; var_t *v; char *value; if (exp->ex_type != EX_MACRO) { log_error("exp_eval_macro: bad type"); return NULL; } stage = vtable_get(mailspec, "stage"); if (stage == NULL) { log_error("exp_eval_macro: milter stage not set"); return NULL; } value = milter_macro_lookup(*stage, exp->ex_data, mailspec); if (value == NULL) { return EXP_EMPTY; } v = var_create(VT_STRING, exp->ex_data, value, VF_KEEPNAME | VF_COPYDATA | VF_EXP_FREE); if (v == NULL) { log_error("exp_eval_macro: var_create failed"); return NULL; } return v; }
int spamd_query(milter_stage_t stage, char *name, var_t *attrs) { int sock = 0; var_t *symbols = NULL; int n; char recv_header[BUFLEN]; char buffer[BUFLEN]; char *p, *q; char *message = NULL; VAR_INT_T spam; VAR_FLOAT_T score; VAR_INT_T *message_size; long header_size, size; /* * Build received header */ header_size = spamd_header(attrs, recv_header, sizeof recv_header); if (header_size == -1) { log_error("spamd_query: spamd_header failed"); goto error; } log_debug("spamd_query: received header:\n%s", recv_header); /* * Get message size */ message_size = vtable_get(attrs, "message_size"); if (message_size == NULL) { log_error("spamd_query: vtable_get failed"); goto error; } size = header_size + *message_size; /* * Allocate message buffer */ message = (char *) malloc(size + 1); if (message == NULL) { log_sys_error("spamd_query: malloc"); goto error; } /* * Dump message */ memcpy(message, recv_header, header_size); if (milter_dump_message(message + header_size, size - header_size + 1, attrs) == -1) { log_error("spamd_query: milter_dump_message failed"); goto error; } snprintf(buffer, sizeof(buffer), "SYMBOLS SPAMC/1.2\r\n" "Content-length: %ld\r\n\r\n", size); sock = sock_connect_rr(&spamd_srr); if (sock == -1) { log_error("spamd_query: sock_connect failed"); goto error; } /* * Write spamassassin request */ if (write(sock, buffer, strlen(buffer)) == -1) { log_sys_error("spamd_query: write"); goto error; } /* * Write message */ if (write(sock, message, size) == -1) { log_sys_error("spamd_query: write"); goto error; } /* * Read response */ n = read(sock, buffer, sizeof buffer - 1); if (n == -1) { log_sys_error("spamd_query: read"); goto error; } buffer[n] = 0; /* * No answer. Seen when spamd ran out of mem. */ if (n == 0) { log_error("spamd_query: no data received"); goto error; } /* * Parse response */ p = buffer; if (strncmp(p, SPAMD_SPAMD, SPAMD_SPAMDLEN)) { spamd_printable_buffer(p, SPAMD_SPAMDLEN + 1); log_error("spamd_query: protocol error: expected='%s' " "received='%s'", SPAMD_SPAMD, p); goto error; } p += SPAMD_SPAMDLEN; if (strncmp(p, SPAMD_VERSION, SPAMD_VERSIONLEN)) { spamd_printable_buffer(p, SPAMD_VERSIONLEN + 1); log_notice("spamd_query: protocol version mismtach: " "expected='%s' received='%s'", SPAMD_VERSION, p); } p += SPAMD_VERSIONLEN; p = strstr(p, SPAMD_EX_OK); if(p == NULL) { log_error("spamd_query: spamd returned non EX_OK"); goto error; } /* * Spamd returns 2 lines. Read 2nd line if neccessary. */ p += SPAMD_EX_OKLEN; if(strlen(p) <= 2) { /* '\r\n' */ n = read(sock, buffer, sizeof(buffer)); if (n == -1) { log_sys_error("spamd_query: read"); goto error; } buffer[n] = 0; p = buffer; } else { p += 2; /* '\r\n' */ } /* * Parse results */ if(strncmp(p, SPAMD_SPAM, SPAMD_SPAMLEN)) { spamd_printable_buffer(p, SPAMD_SPAMLEN + 1); log_error("spamd_query: protocol error: expected='%s' " "received='%s'", SPAMD_SPAM, p); goto error; } p += SPAMD_SPAMLEN; if(!strncmp(p, SPAMD_TRUE, SPAMD_TRUELEN)) { spam = 1; p += SPAMD_TRUELEN; } else if(!strncmp(p, SPAMD_FALSE, SPAMD_FALSELEN)) { spam = 0; p += SPAMD_FALSELEN; } else { spamd_printable_buffer(p, (SPAMD_TRUELEN > SPAMD_FALSELEN ? SPAMD_TRUELEN: SPAMD_FALSELEN) + 1); log_error("spamd_query: protocol error: expected: '%s|%s' " "received='%s'", SPAMD_TRUE, SPAMD_FALSE, p); goto error; } /* * Cut score. */ q = strchr(p, ' '); if (q == NULL) { log_error("spamd_query: protocol error: couldn't find the " "next space character"); goto error; } *q++ = 0; score = (VAR_FLOAT_T) strtod(p, NULL); /* * Set SYMBOLS */ p = strchr(q, '\r'); if (p == NULL) { log_error("spamd_query: protocol error: couldn't find the " "start of the spamd symbols"); goto error; } p += 4; /* \r\n\r\n */ q = strchr(p, '\r'); if (q == NULL) { log_error("spamd_query: protocol error: couldn't find the " "end of the spamd symbols"); goto error; } *q = 0; log_message(LOG_ERR, attrs, "spamd: spam=%d score=%.1f symbols=%s", spam, score, p); symbols = var_create(VT_LIST, "spamd_symbols", NULL, VF_KEEPNAME | VF_CREATE); if (symbols == NULL) { log_error("spamd_query: var_create failed"); goto error; } do { q = strchr(p, ','); if (q) { *q = 0; } if (vlist_append_new(symbols, VT_STRING, NULL, p, VF_COPYDATA) == -1) { log_error("spamd_query: vlist_append failed"); goto error; } p = q + 1; } while (q); if (vtable_setv(attrs, VT_INT, "spamd_spam", &spam, VF_KEEPNAME | VF_COPYDATA, VT_FLOAT, "spamd_score", &score, VF_KEEPNAME | VF_COPYDATA, VT_NULL)) { log_error("spamd_query: vtable_setv failed"); goto error; } if (vtable_set(attrs, symbols)) { log_error("spamd_query: vtable_set failed"); goto error; } close(sock); free(message); return 0; error: if (message) { free(message); } if (sock > 0) { close(sock); } if (symbols) { var_delete(symbols); } return -1; }
acl_action_type_t msgmod(milter_stage_t stage, char *stagename, var_t *mailspec, void *data, int depth) { msgmod_t *mm = data; void *ctx; acl_action_type_t action = ACL_ERROR; var_t **args = NULL; int argc; int size; var_t *v, *copy; int i; exp_t *exp; ll_t *ll; ll_entry_t *pos; /* * Get milter ctx pointer */ ctx = vtable_get(mailspec, "milter_ctx"); if (ctx == NULL) { log_error("msgmod: ctx not set"); goto error; } /* * Evaluate arguments */ argc = mm->mm_args->ll_size; size = (argc + 1) * sizeof (var_t *); args = (var_t **) malloc(size); if (args == NULL) { log_sys_error("msgmod: malloc"); goto error; } memset(args, 0, size); ll = mm->mm_args; pos = LL_START(ll); for (i = 0; i < argc; ++i) { exp = ll_next(ll, &pos); if (exp == NULL) { log_die(EX_SOFTWARE, "msgmod: empty argument"); } v = exp_eval(exp, mailspec); if (v == NULL) { log_error("msgmod: exp_eval failed"); goto error; } // Cast all aruments to VT_STRING if (v->v_type != VT_STRING) { copy = var_cast_copy(VT_STRING, v); if (copy == NULL) { log_error("msgmod: var_cast_copy failed"); goto error; } exp_free(v); /* * args are freed using exp_free. Set VF_EXP_FREE to * free copy. */ copy->v_flags |= VF_EXP_FREE; v = copy; } args[i] = v; } if (mm->mm_callback(ctx, argc, args)) { log_error("msgmod: mm_callback failed"); goto error; } action = ACL_NONE; error: /* * Free args */ for (i = 0; args[i]; ++i) { exp_free(args[i]); } if (args) { free(args); } return action; }