• Patch: Elm ME+ 2.5 PLalpha51 -> Elm ME+ 2.5 PLalpha52 [3/7] (4/6)

    From Kari Hurtta@21:1/5 to All on Mon Jun 8 19:47:03 2020
    [continued from previous message]

    + if (check_domain_seen) {
    + if (filename) {
    + lib_error(CATGETS(elm_msg_cat, MeSet, MeMsgIDDubParamFile,
    + "Duplicate paramater %Q on message-id option %Q on line %d on file %s"),
    + f,this_value,lineno,filename);
    +
    + } else {
    + lib_error(CATGETS(elm_msg_cat, MeSet, MeMsgIDDubParam,
    + "Duplicate paramater %Q on message-id option %Q."),
    + f,this_value);
    + }
    +
    + ok = 0;
    + }
    +
    + if (parse_check_domain(a,read_flags)) {
    + DPRINT(Debug,14,(&Debug,"message_id_func: Parsed %s\n",
    + f));
    + check_domain_seen = 1;
    + } else {
    + goto bad_param;
    + }
    +
    + } else if (0 == strncmp(f,MIN_DOMAIN_LABELS_eq,len)) {
    + char * a = f+len;
    +
    + if (min_domain_labels_seen) {
    + if (filename) {
    + lib_error(CATGETS(elm_msg_cat, MeSet, MeMsgIDDubParamFile,
    + "Duplicate paramater %Q on message-id option %Q on line %d on file %s"),
    + f,this_value,lineno,filename);
    +
    + } else {
    + lib_error(CATGETS(elm_msg_cat, MeSet, MeMsgIDDubParam,
    + "Duplicate paramater %Q on message-id option %Q."),
    + f,this_value);
    + }
    +
    + ok = 0;
    + }
    +
    +
    + if (parse_min_domain_labels(a)) {
    + DPRINT(Debug,14,(&Debug,"message_id_func: Parsed %s\n",
    + f));
    + min_domain_labels_seen = 1;
    + } else {
    + goto bad_param;
    + }
    +
    + } else
    + goto bad_param;
    +
    + } else {
    + bad_param:
    +
    + if (filename) {
    + lib_error(CATGETS(elm_msg_cat, MeSet, MeMsgIDBadParamFile,
    + "Invalid parameter %Q on message-id option %Q on line %d on file %s"),
    + f,this_value,lineno,filename);
    +
    + } else {
    + lib_error(CATGETS(elm_msg_cat, MeSet, MeMsgIDBadParam, + "Invalid parameter %Q on message-id option %Q."),
    + f,this_value);
    + }
    + ok = 0;
    + }
    + }
    + }
    +
    + #ifdef FALLBACKMSGIDDOM
    + if (! fallback_initialized && message_id_localspec > msgidlocal_none)
    + add_fallback_domain(FALLBACKMSGIDDOM);
    + #endif
    +
    + failparse:
    + free(temp); temp = NULL;
    +
    + if (reset_saved_on_failure && !ok) {
    + DPRINT(Debug,14, (&Debug, "message_id_func: resetting unparsed saved value: "));
    +
    + if (saved_localspec) {
    + DPRINT(Debug,14, (&Debug, "%s", saved_localspec));
    + free(saved_localspec);
    + saved_localspec = NULL;
    + }
    +
    + if (saved_domspec) {
    + DPRINT(Debug,14, (&Debug, "@%s", saved_domspec));
    + free(saved_domspec);
    + saved_domspec = NULL;
    + }
    +
    + if (saved_params) {
    + DPRINT(Debug,14, (&Debug, "; %s", saved_params));
    + free(saved_params);
    + saved_params = NULL;
    + }
    +
    + DPRINT(Debug,14, (&Debug, "\n"));
    + }
    +
    + if (ok) {
    + message_id_set = 1;
    +
    + DPRINT(Debug,14, (&Debug, "message_id_func: unparsed saved value: "));
    +
    + if (saved_localspec) {
    + DPRINT(Debug,14, (&Debug, "%s", saved_localspec));
    + }
    +
    + if (saved_domspec) {
    + DPRINT(Debug,14, (&Debug, "@%s", saved_domspec));
    + }
    +
    + if (saved_params) {
    + DPRINT(Debug,14, (&Debug, "; %s", saved_params));
    + }
    +
    + DPRINT(Debug,14, (&Debug, "\n"));
    + }
    +
    + } else { /* not enter -- return message-id setting on *value */
    + char * result = NULL;
    +
    + char * generated_localspec = NULL;
    + char * generated_domspec = NULL;
    + char * generated_params = NULL;
    + char * comment = NULL;
    +
    + if (! message_id_set) {
    + configure_message_id();
    + }
    +
    + if (saved_localspec)
    + result = strmcat(result,saved_localspec);
    +
    + else if (generated_localspec ||
    + (generated_localspec = generate_localspec(&ok))) {
    + result = strmcat(result,generated_localspec);
    + } else
    + result = strmcat(result,INVALID);
    +
    + if (saved_domspec) {
    + result = strmcat(result,"@");
    + result = strmcat(result,saved_domspec);
    +
    + } else if (generated_domspec ||
    + (message_id_localspec != msgidlocal_none &&
    + (generated_domspec = generate_domspec(&ok)))) {
    + result = strmcat(result,"@");
    + result = strmcat(result,generated_domspec);
    + } else if (message_id_localspec != msgidlocal_none) {
    + result = strmcat(result,"@");
    + result = strmcat(result,INVALID);
    + }
    +
    + if (saved_params) {
    + result = strmcat(result,PARAM_SEPARATOR);
    + result = strmcat(result,saved_params);
    + } else if (generated_params ||
    + (message_id_localspec != msgidlocal_none &&
    + (generated_params = generate_params(&ok)))) {
    + result = strmcat(result,PARAM_SEPARATOR);
    +
    + result = strmcat(result,generated_params);
    + }
    +
    + /* Generate expanded value as comment */
    +
    + if (generated_localspec ||
    + (generated_localspec = generate_localspec(&ok))) {
    + comment = strmcat(comment,generated_localspec);
    + } else
    + comment = strmcat(comment,INVALID);
    +
    + if (generated_domspec ||
    + (message_id_localspec != msgidlocal_none &&
    + (generated_domspec = generate_domspec(&ok)))) {
    + comment = strmcat(comment,"@");
    + comment = strmcat(comment,generated_domspec);
    + } else if (message_id_localspec != msgidlocal_none) {
    + comment = strmcat(comment,"@");
    + comment = strmcat(comment,INVALID);
    + }
    +
    + if (generated_params ||
    + (message_id_localspec != msgidlocal_none &&
    + (generated_params = generate_params(&ok)))) {
    + comment = strmcat(comment,PARAM_SEPARATOR);
    +
    + comment = strmcat(comment,generated_params);
    + }
    +
    + if (result && comment) {
    + if (0 != strcmp(result,comment)) {
    + result = strmcat(result,COMMENT_SEP);
    + result = strmcat(result,comment);
    + }
    + }
    +
    + if (*value)
    + free(*value);
    + *value = result; result = NULL;
    +
    + if (generated_localspec) {
    + free(generated_localspec);
    + generated_localspec = NULL;
    + }
    + if (generated_domspec) {
    + free(generated_domspec);
    + generated_domspec = NULL;
    + }
    + if (generated_params) {
    + free(generated_params);
    + generated_params = NULL;
    + }
    + if (comment) {
    + free(comment);
    + comment = NULL;
    + }
    +
    + }
    +
    + DPRINT(Debug,14, (&Debug, "message_id_func=%d%s%s",
    + ok,
    + ok ? " (succeed)" : " FAILED",
    + enter ? " (enter) " : " (return value)"));
    + if (*value) {
    + DPRINT(Debug,14, (&Debug, "; *value=%Q",*value));
    + }
    +
    + DPRINT(Debug,14, (&Debug, "\n"));
    +
    + return ok;
    + }
    +
    + /* Does NOT include all letters -- not \0 terminated */
    + static const char SYMBOLS[] = {
    + 'A','B','C','D','E','F','G','H', 'J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z',
    + 'a','b','c','d','e','f','g','h','i','j','k', 'm','n','p', 'r','s','t','u','v','w','x','y','z',
    + '2','3','4','5','6','7','8','9'
    + };
    +
    + /* Generate left side of message-id for
    + msgidlocal_md5, and
    + msgidlocal_devurandom
    +
    + result is malloced
    + */
    + static char * octectvalue_to_left P_((const unsigned char data[],
    + const size_t data_len));
    + static char * octectvalue_to_left(data,data_len)
    + const unsigned char data[];
    + const size_t data_len;
    + {
    + /* This produces different result on 64-bit ad 32-bit enviroment */
    +
    + static const size_t base = sizeof SYMBOLS;
    + static unsigned int bits = 0;
    + static int check = 0; /* Calculate bits from base once */
    +
    + char * ret = NULL;
    + size_t ret_len = 0;
    + size_t malloc_len = 1 + data_len / sizeof (unsigned long); /* \0 and separating . characters */
    + size_t expand = 0;
    + size_t i;
    + char * temp = NULL;
    + size_t tempsize;
    +
    + if (!check) {
    + size_t x;
    +
    + DPRINT(Debug,14,(&Debug, "octectvalue_to_left: base=%zu\n",base));
    +
    + for (i = 0; i < base; i++) {
    + if (!SYMBOLS[i] || !isascii(SYMBOLS[i]) || !isprint(SYMBOLS[i])) { + DPRINT(Debug,1,(&Debug, "octectvalue_to_left: #%zu bad symbol %d\n",
    + i,SYMBOLS[i]));
    +
    + panic("MAILER PANIC",__FILE__,__LINE__,
    + "octectvalue_to_left",
    + "Bad symbol",0);
    + }
    +
    + }
    +
    + i = base;
    + bits = 0;
    +
    + while (i > 0) {
    + bits++;
    + i >>= 1;
    + }
    +
    + x = 1 << bits;
    +
    + DPRINT(Debug,14,(&Debug, "octectvalue_to_left: bits=%u => %zu",
    + bits,x));
    +
    + if (x > base) { /* Round down bits */
    + DPRINT(Debug,14,(&Debug, " > base %zu",base));
    +
    + bits--;
    +
    + x = 1 << bits;
    + DPRINT(Debug,14,(&Debug, ", reducing bits=%u (=> %zu)",
    + bits,x));
    + } else {
    +
    + DPRINT(Debug,14,(&Debug, " OK -- base %zu",base));
    + }
    + DPRINT(Debug,14,(&Debug, "\n"));
    +
    + check = 1;
    + }
    +
    + /* Is this enough ? */
    +
    + tempsize = (sizeof (unsigned long) * 8) / bits +1;
    +
    + temp = safe_malloc(tempsize);
    +
    + /* Does not need to be correct */
    +
    + expand = (data_len * 8) / bits;
    +
    + DPRINT(Debug,14,(&Debug, "octectvalue_to_left: data_len=%zu => expand=%zu",
    + data_len,expand));
    + malloc_len += expand;
    + DPRINT(Debug,14,(&Debug, ", malloc_len=%zu, bits=%u => tempsize=%zu\n",
    + malloc_len,bits,tempsize));
    +
    + ret = safe_malloc(malloc_len);
    +
    + #define ADD(x) { \
    + if (malloc_len < ret_len+1) { \
    + size_t old = malloc_len; \
    + malloc_len = ret_len+8; \
    + DPRINT(Debug,14,(&Debug, \
    + "octectvalue_to_left: malloc_len=%zu => %zu\n", \ + old,malloc_len)); \
    + ret = safe_realloc(ret,malloc_len); \
    + } \
    + ret[ret_len++] = (x); \
    + } while(0)
    +
    + for (i = 0; i < data_len; ) {
    + size_t j;
    + size_t y;
    + unsigned long r;
    +
    + unsigned long unit = 0;
    +
    + /* Collect unsigned long worth of octets (if available) */
    +
    + for (j = 0; j < sizeof unit && i < data_len; j++) {
    +
    + unit <<= 8;
    + unit |= data[i++];
    + }
    +
    + /* Add . between values */
    + if (ret_len > 0)
    + ADD('.');
    +
    + y = tempsize;
    +
    + do {
    + unsigned long t;
    +
    + t = (unit % base );
    + r = (unit / base );
    + unit = r;
    +
    + y--;
    + temp[y] = SYMBOLS[t];
    +
    + } while (r && y > 0);
    +
    + if (r) {
    + DPRINT(Debug,14,(&Debug, "octectvalue_to_left: temp buffer too small -- %zu remainder\n",r));
    + ADD('~');
    + }
    +
    + while (y < tempsize) {
    + ADD(temp[y]);
    + y++;
    + }
    + }
    +
    + free(temp);
    +
    + if (malloc_len != ret_len+1) { /* Adjuts for final \0 */
    + size_t old = malloc_len;
    + malloc_len = ret_len+1;
    + DPRINT(Debug,14,(&Debug, "octectvalue_to_left: malloc_len=%zu => %zu\n",old,malloc_len));
    + ret = safe_realloc(ret,malloc_len);
    + }
    + ret[ret_len] = '\0';
    +
    + #undef ADD
    +
    + DPRINT(Debug,14,(&Debug, "octectvalue_to_left=%Q, ret_len=%zu, malloc_len=%zu\n",ret,ret_len,malloc_len));
    +
    + return ret;
    + }
    +
    + static int match_to_domain P_((enum domain_names d, const char *old_domain_part));
    + static int match_to_domain(d,old_domain_part)
    + enum domain_names d;
    + const char *old_domain_part;
    + {
    + int ourdom = 0;
    +
    + if (d < 0 || d >= NUM_dname)
    + panic("MAILER PANIC",__FILE__,__LINE__,
    + "match_to_domain",
    + "Bad domain name index",0);
    +
    + if (message_id_dinfo[d]) {
    + if (DOMAIN_INFO_magic != message_id_dinfo[d]->magic)
    + panic("MAILER PANIC",__FILE__,__LINE__,
    + "match_to_domain",
    + "Bad magic number (domain_info)",0);
    +
    + if (message_id_dinfo[d]->dompart &&
    + message_id_dinfo[d]->dompart[0] &&
    + 0 == strcmp(message_id_dinfo[d]->dompart,
    + old_domain_part)) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "match_to_domain: old message-id domain %Q matches to generated domain part (message_id #%d %s)\n",
    + old_domain_part,
    + d,domain_names_d[d]));
    + ourdom = 1;
    + }
    +
    + if (message_id_dinfo[d]->rewrite &&
    + message_id_dinfo[d]->rewrite[0] &&
    + 0 == strcmp(message_id_dinfo[d]->rewrite,
    + old_domain_part)) {
    + DPRINT(Debug,14,(&Debug,
    + "match_to_domain: old message-id domain %Q matches to rewritten domain name on name check (message_id #%d %s)\n",
    + old_domain_part,
    + d,domain_names_d[d]));
    + ourdom = 1;
    + }
    + }
    +
    + return ourdom;
    + }
    +
    + /* Result is malloced */
    +
    + static char *get_msg_domain P_((enum domain_names d));
    + static char *get_msg_domain(d)
    + enum domain_names d;
    + {
    + if (d < 0 || d >= NUM_dname)
    + panic("MAILER PANIC",__FILE__,__LINE__,
    + "get_msg_domain",
    + "Bad domain name index",0);
    +
    + if (message_id_dinfo[d]) {
    + if (DOMAIN_INFO_magic != message_id_dinfo[d]->magic)
    + panic("MAILER PANIC",__FILE__,__LINE__,
    + "get_msg_domain",
    + "Bad magic number (domain_info)",0);
    +
    +
    + if (message_id_dinfo[d]->dompart &&
    + message_id_dinfo[d]->dompart[0]) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "get_msg_domain: message_id #%d %s is %Q\n",
    + d,domain_names_d[d],
    + message_id_dinfo[d]->dompart));
    +
    + return safe_strdup(message_id_dinfo[d]->dompart);
    + }
    + }
    +
    + return NULL;
    + }
    +
    +
    + /* Count numbers of domain labels, domain literals are
    + assumed to be handled separately and not accepted here
    +
    + Does not count empty domain labels (these also flag error)
    + */
    +
    + static int count_domain_labels(const char *dom,int * ok_p);
    + static int count_domain_labels(dom,ok_p)
    + const char *dom;
    + int * ok_p;
    + {
    + int count = 0;
    + const char * a;
    + int len = 0;
    +
    + int start_of_label = 1;
    +
    + /* Note: \. is not considered as domain label separator */
    +
    + if (ok_p)
    + *ok_p = (dom[0] != '\0');
    +
    + for (a = dom; *a; a += len) {
    + len = rfc822_toklen(a); /* Returns 2 for \. */
    +
    + if (1 == len && '.' == *a) {
    + if (start_of_label) {
    + DPRINT(Debug,14,(&Debug,
    + "count_domain_labels: %Q -- several dots (..) or dot (.) on beginning of domain\n",
    + dom));
    +
    + if (ok_p)
    + *ok_p = 0;
    + } else {
    + start_of_label = 1;
    + }
    +
    + } else if (start_of_label) {
    + start_of_label = 0;
    + count++;
    + }
    +
    + if ('.' != *a && '\\' != *a && rfc822_special(*a)) {
    +
    + /* !!!! %.*Q can not used here as format argument */
    + DPRINT(Debug,14,(&Debug,
    + "count_domain_labels: %Q -- rfc822 special (%.*s) seen\n",
    + dom,len,a));
    +
    + if (ok_p)
    + *ok_p = 0;
    + }
    +
    + if (whitespace(*a)) {
    + /* !!!! %.*Q can not used here as format argument */
    + DPRINT(Debug,14,(&Debug,
    + "count_domain_labels: %Q -- whitespace (%.*s) seen\n",
    + dom,len,a));
    +
    + if (ok_p)
    + *ok_p = 0;
    +
    + }
    + }
    +
    + if (start_of_label) {
    + DPRINT(Debug,14,(&Debug,
    + "count_domain_labels: %Q -- dot (.) on end of domain or empty string given\n",
    + dom));
    +
    + if (ok_p)
    + *ok_p = 0;
    + }
    +
    + DPRINT(Debug,14,(&Debug,
    + "count_domain_labels=%d labels",
    + count));
    + if (ok_p) {
    + DPRINT(Debug,14,(&Debug,
    + ", *ok_p=%d%s",
    + *ok_p,
    + *ok_p ? " OK" : " FAILED"));
    + }
    +
    + DPRINT(Debug,14,(&Debug,", domain %Q\n",dom));
    +
    + return count;
    + }
    +
    + /* Return rewritten string if domain check succeed, also update message_id_dinfo
    + resuld is malloced
    + */
    +
    + static char * check_msg_domain0 P_((struct domain_info * I,
    + const char * dom,
    + struct cancel_data ** cancel_p, + const struct schedule_timelimit * now,
    + const struct schedule_timelimit * default_valid_until /* for other data */
    + ));
    +
    + static char * check_msg_domain0(I,dom,cancel_p,now,default_valid_until)
    + struct domain_info * I;
    + const char * dom;
    + struct cancel_data ** cancel_p;
    + const struct schedule_timelimit * now;
    + const struct schedule_timelimit * default_valid_until /* for other data */;
    + {
    + char * ret = NULL;
    +
    + if (DOMAIN_INFO_magic != I->magic)
    + panic("MAILER PANIC",__FILE__,__LINE__,
    + "check_msg_domain0",
    + "Bad magic number (domain_info)",0);
    +
    + if ('[' == dom[0]) {
    + int len = rfc822_toklen(dom);
    +
    + if (len < 2 || dom[len] || dom[len-1] != ']') {
    + DPRINT(Debug,14,(&Debug,
    + "check_msg_domain0: domain %Q failed to parse as literal\n",
    + dom));
    + I->domstat = check_dname_no_routine;
    + I->domcheck = cds_bad_syntax;
    +
    + if (I->dompart)
    + free(I->dompart);
    + I->dompart = NULL;
    + if (I->rewrite)
    + free(I->rewrite);
    + I->rewrite = NULL;
    +
    + I->valid_until = NO_schedule_timelimit;
    +
    + ret = NULL;
    + goto done;
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "check_msg_domain0: domain %Q parsed as literal\n",
    + dom));
    + I->domstat = check_dname_no_routine;
    + I->domcheck = cds_disabled_ok;
    + I->dompart = strmcpy(I->dompart,dom);
    + if (I->rewrite)
    + free(I->rewrite);
    + I->rewrite = NULL;
    +
    + I->valid_until = NO_schedule_timelimit;
    +
    + ret = safe_strdup(dom);
    + goto done;
    + }
    +
    + } else {
    + const char * whitelisted =
    + is_whitelisted_msgid_domain(dom);
    +
    + const char * reserved_name = NULL;
    + const char * dummy_name = NULL;
    +
    + if (whitelisted) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "check_msg_domain0: domain %Q whitelisted on %Q\n",
    + whitelisted,dom));
    +
    + I->domstat = check_dname_no_routine;
    + I->domcheck = cds_whitelisted;
    + I->dompart = strmcpy(I->dompart,dom);
    + if (I->rewrite)
    + free(I->rewrite);
    + I->rewrite = NULL;
    +
    + I->valid_until = NO_schedule_timelimit;
    +
    + ret = safe_strdup(dom);
    + goto done;
    +
    + } else if ((reserved_name = is_special_use_domain(dom))) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "check_msg_domain0: reserved domain %Q usupported on %Q\n",
    + reserved_name,dom));
    +
    + I->domstat = check_dname_no_routine;
    + I->domcheck = cds_reserved;
    +
    + I->dompart = strmcpy(I->dompart,dom);
    + if (I->rewrite)
    + free(I->rewrite);
    + I->rewrite = NULL;
    +
    + I->valid_until = NO_schedule_timelimit;
    +
    + goto done;
    +
    + } else if ((dummy_name = matches_dummy_domain(dom))) {
    +
    + DPRINT(Debug,14,(&Debug,
    + "check_msg_domain0: dummy domain %Q rejected on %Q\n",
    + dummy_name,dom));
    +
    + I->domstat = check_dname_no_routine;
    + I->domcheck = cds_fail;
    +
    + if (I->rewrite)
    + free(I->rewrite);
    + I->rewrite = NULL;
    +
    + I->valid_until = NO_schedule_timelimit;
    +
    + goto done;
    +
    + } else if (I->dompart &&
    + 0 == strcmp(I->dompart,dom)) {
    +
    + if (schedule_have_timelimit(& (I->valid_until))) {
    +
    + if (schedule_valid_until_ok(& (I->valid_until),now)) {
    +
    + char * A = schedule_timeout_string(& (I->valid_until));
    +
    + DPRINT(Debug,14,(&Debug,
    + "check_msg_domain0: Entry %Q valid (not expired)",
    + I->dompart));
    + if (A) {
    + DPRINT(Debug,14,(&Debug, ", valid until %s",A));
    + free(A); A = NULL;
    + }
    + } else
    + goto done;
    + } else {
    + DPRINT(Debug,14,(&Debug,
    + "check_msg_domain0: Entry %Q valid (no timelimit)",
    + I->dompart));
    + }
    +
    + DPRINT(Debug,14,(&Debug, ", domcheck = %d",I->domcheck));
    + switch (I->domcheck) {
    + case cds_reserved:
    + DPRINT(Debug,14,(&Debug, " cds_reserved\n"));
    + goto done;
    + case cds_no_routine:
    + DPRINT(Debug,14,(&Debug, " cds_no_routine"));
    + break;
    + case cds_fail:
    + DPRINT(Debug,14,(&Debug, " cds_fail"));
    + break;
    + case cds_none:
    + DPRINT(Debug,14,(&Debug, " cds_none"));
    + break;
    + case cds_ok:
    + DPRINT(Debug,14,(&Debug, " cds_ok"));
    + if (I->rewrite) {
    + DPRINT(Debug,14,(&Debug, ", rewrite %Q",I->rewrite));
    + ret = safe_strdup(I->rewrite);
    + } else
    + ret = safe_strdup(I->dompart);
    + DPRINT(Debug,14,(&Debug, "\n"));
    + goto done;
    + case cds_bad_syntax:
    + DPRINT(Debug,14,(&Debug, " cds_bad_syntax\n"));
    + goto done;
    + case cds_whitelisted:
    + DPRINT(Debug,14,(&Debug, " cds_whitelisted\n"));
    + ret = safe_strdup(I->dompart);
    + goto done;
    + case cds_disabled_ok:
    + DPRINT(Debug,14,(&Debug, " cds_disabled_ok\n"));
    + ret = safe_strdup(I->dompart);
    + goto done;
    + }
    +
    + DPRINT(Debug,14,(&Debug, ", domstat = %d",I->domstat));
    + switch (I->domstat) {
    + case check_dname_no_routine:
    + DPRINT(Debug,14,(&Debug, " check_dname_no_routine"));
    + break;
    + case check_dname_query_blacklisted:
    + DPRINT(Debug,14,(&Debug, " check_dname_query_blacklisted\n")); + goto done;
    + case check_dname_failure:
    + DPRINT(Debug,14,(&Debug, " check_dname_failure"));
    + /* Assume temporal failure */
    + break;
    + case check_dname_not_found:
    + DPRINT(Debug,14,(&Debug, " check_dname_not_found\n"));
    + goto done;
    + case check_dname_have_name:
    + DPRINT(Debug,14,(&Debug, " check_dname_have_name"));
    + /* Should not happen */
    + if (I->rewrite) {
    + DPRINT(Debug,14,(&Debug, ", rewrite %Q",I->rewrite));
    + ret = safe_strdup(I->rewrite);
    + } else
    + ret = safe_strdup(I->dompart);
    + DPRINT(Debug,14,(&Debug, "\n"));
    + goto done;
    + case check_dname_bad_syntax:
    + DPRINT(Debug,14,(&Debug, " check_dname_bad_syntax\n"));
    + goto done;
    + }
    + DPRINT(Debug,14,(&Debug, "\n"));
    +
    + }
    +
    + if (!ret) {
    + I->domstat = check_dname_no_routine;
    + I->domcheck = cds_none;
    +
    + I->dompart = strmcpy(I->dompart,dom);
    + if (I->rewrite)
    + free(I->rewrite);
    + I->rewrite = NULL;
    +
    + I->valid_until = NO_schedule_timelimit;
    +
    + if (min_domain_labels > 0) {
    + int ok = 1;
    +
    + int num_labels = count_domain_labels(dom,&ok);
    +
    + DPRINT(Debug,14,(&Debug,
    + "check_msg_domain0: domain %Q have %d domain label(s), %s",
    + dom,num_labels,ok ? "syntax OK" : "parse failed"));
    +
    + if (!ok) {
    + DPRINT(Debug,14,(&Debug, "\n"));
    + I->domcheck = cds_bad_syntax;
    + goto done;
    + } else if (num_labels < min_domain_labels) {
    + DPRINT(Debug,14,(&Debug,
    + ", skipping DNS check, %d domain labels required\n",
    + min_domain_labels));
    + I->domcheck = cds_fail;
    + goto done;
    + }
    +
    + DPRINT(Debug,14,(&Debug, "\n"));
    + }
    +
    +
    +
    + switch (msg_checkdom_mode) {
    +
    + case msg_checkdom_tag:
    + #ifdef USE_DLOPEN
    + I->domstat = shared_check_dname(I->dompart,&(I->rewrite),
    + msg_verifydom_tag,
    + now,
    + default_valid_until,
    + &(I->valid_until),
    + NULL /* No error message? */, + cancel_p);
    + #else
    + DPRINT(Debug,14,(&Debug, "check_msg_domain0: no shared routines available\n"));
    + I->domstat = check_dname_no_routine;
    + #endif
    + break;
    + case msg_checkdom_none:
    + DPRINT(Debug,14,(&Debug, "check_msg_domain0: Domain verify disabled.\n"));
    + break;
    + case msg_checkdom_shared:
    + #ifdef USE_DLOPEN
    + I->domstat = shared_check_dname(I->dompart,&(I->rewrite),
    + NULL /* No tag */,
    + now,
    + default_valid_until,
    + &(I->valid_until),
    + NULL /* No error message? */, + cancel_p);
    + #else
    + DPRINT(Debug,14,(&Debug, "check_msg_domain0: no shared routines available\n"));
    + I->domstat = check_dname_no_routine;
    + #endif
    + break;
    + case NUM_msg_check_dom_mode:
    + break;
    + }
    +
    + DPRINT(Debug,14,(&Debug, "check_msg_domain0: %Q: domstat = %d",
    + I->dompart,I->domstat));
    + switch (I->domstat) {
    + case check_dname_no_routine:
    + DPRINT(Debug,14,(&Debug, " check_dname_no_routine"));
    + I->domcheck = cds_no_routine;
    +
    + if (msg_checkdom_mode != msg_checkdom_none) {
    + DPRINT(Debug,14,(&Debug, " (disabling domain verify)"));
    + msg_checkdom_mode = msg_checkdom_none;
    + }
    + break;
    + case check_dname_query_blacklisted:
    + DPRINT(Debug,14,(&Debug, " check_dname_query_blacklisted"));
    + I->domcheck = cds_reserved;
    + break;
    + case check_dname_failure:
    + DPRINT(Debug,14,(&Debug, " check_dname_failure"));
    + I->domcheck = cds_fail;
    + break;
    + case check_dname_not_found:
    + DPRINT(Debug,14,(&Debug, " check_dname_not_found"));
    + I->domcheck = cds_fail;
    + break;
    + case check_dname_have_name:
    + DPRINT(Debug,14,(&Debug, " check_dname_have_name"));
    + I->domcheck = cds_ok;
    + if (I->rewrite) {
    + DPRINT(Debug,14,(&Debug, ", rewrite %Q",I->rewrite));
    + ret = safe_strdup(I->rewrite);
    + } else
    + ret = safe_strdup(I->dompart);
    + break;
    + case check_dname_bad_syntax:
    + DPRINT(Debug,14,(&Debug, " check_dname_bad_syntax"));
    + I->domcheck = cds_bad_syntax;
    + break;
    + }
    +
    +
    + if (schedule_have_timelimit(& (I->valid_until))) {
    + char * A = schedule_timeout_string(& (I->valid_until));
    +
    + if (A) {
    + DPRINT(Debug,14,(&Debug, ", valid until %s",A));
    + free(A); A = NULL;
    + }
    + DPRINT(Debug,14,(&Debug, "\n"));
    +
    + update_next_domver_cleanup(& (I->valid_until));
    + } else {
    + DPRINT(Debug,14,(&Debug, ", no timelimit\n"));
    + }
    +
    + if (cancel_p && *cancel_p && is_canceled(*cancel_p)) {
    + DPRINT(Debug,14,(&Debug, "check_msg_domain0: DNS lookup canceled\n"));
    + }
    + }
    + }
    +
    + done:
    + DPRINT(Debug,14,(&Debug,
    + "check_msg_domain0="));
    + if (ret) {
    + DPRINT(Debug,14,(&Debug,"%Q",ret));
    + } else {
    + DPRINT(Debug,14,(&Debug,"NULL (failure)"));
    + }
    + DPRINT(Debug,14,(&Debug,"; dom=%Q\n",dom));
    +
    + return ret;
    + }
    +
    + static char * check_msg_domain P_((enum domain_names d,const char *dom,
    + struct cancel_data ** cancel_p,
    + const struct schedule_timelimit * now,
    + const struct schedule_timelimit * default_valid_until /* for other data */));
    + static char * check_msg_domain(d,dom,cancel_p,now,default_valid_until)
    + enum domain_names d;
    + const char *dom;
    + struct cancel_data ** cancel_p;
    + const struct schedule_timelimit * now;
    + const struct schedule_timelimit * default_valid_until /* for other data */;
    + {
    + if (d < 0 || d >= NUM_dname)
    + panic("MAILER PANIC",__FILE__,__LINE__,
    + "check_msg_domain",
    + "Bad domain name index",0);
    +
    + if (! message_id_dinfo[d])
    + message_id_dinfo[d] = new_domain_info(dom,cds_none, default_valid_until);
    +
    + return check_msg_domain0(message_id_dinfo[d],dom,cancel_p,
    + now,
    + default_valid_until);
    + }
    +
    +
    + static void free_domlist P_((char ***domlist,
    + size_t *domlist_len));
    + static void free_domlist(domlist,domlist_len)
    + char ***domlist;
    + size_t *domlist_len;
    + {
    + if (*domlist) {
    + size_t x;
    +
    + for (x = 0; x < *domlist_len; x++) {
    + if ((*domlist)[x]) {
    + free((*domlist)[x]);
    + (*domlist)[x] = NULL;
    + }
    + }
    + free(*domlist);
    + *domlist = NULL;
    + }
    + *domlist_len = 0;
    + }
    +
    + /* Result is malloced */
    + static char * left_part_from_devurandom P_((enum message_id_status *ret_p)); + static char * left_part_from_devurandom(ret_p)
    + enum message_id_status *ret_p;
    + {
    +
    + char * left_part = NULL;
    + int retry = 0;
    + int last_retry;
    +
    +
    + do {
    + last_retry = retry;
    +
    + DPRINT(Debug,14, (&Debug,"left_part_from_devurandom: devurandom_used=%d ",devurandom_used));
    + switch (devurandom_used) {
    + case buffer_bad: DPRINT(Debug,14, (&Debug," buffer_bad")); break;
    + case buffer_initialized: DPRINT(Debug,14, (&Debug," buffer_initialized devurandom len %d",
    + devurandom_len));
    + if (devurandom_len > 0) {
    + size_t x;
    + DPRINT(Debug,14,(&Debug," ["));
    +
    + for (x = 0; x < devurandom_len && x < sizeof procuuid_buffer; x++) {
    + DPRINT(Debug,14,(&Debug,"%02x",devurandom_buffer[x]));
    + }
    + DPRINT(Debug,14,(&Debug,"]"));
    + }
    +
    + break;
    + case buffer_used: DPRINT(Debug,14, (&Debug," buffer_used")); break;
    + }
    + if (retry) {
    + DPRINT(Debug,14, (&Debug," retry=%d",retry));
    + }
    + DPRINT(Debug,14, (&Debug,"\n"));
    +
    + switch (devurandom_used) {
    +
    + case buffer_initialized:
    +
    + /* Have data */
    + if (devurandom_len == sizeof devurandom_buffer) {
    +
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: have full %d bytes on devurandom buffer\n",
    + devurandom_len));
    + left_part = octectvalue_to_left(devurandom_buffer,devurandom_len);
    +
    + devurandom_used = buffer_used;
    +
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: consumed devurandom buffer\n"));
    + goto done;
    + } else if (devurandom_len < sizeof devurandom_buffer) {
    + int need = (sizeof devurandom_buffer) - devurandom_len;
    + int len;
    +
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: have data %d bytes on devurandom buffer, need %d bytes more\n",
    + devurandom_len,need));
    +
    + if (-1 == devurandom_fd &&
    + ! open_devurandom()) {
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: devurandom is not open.\n"));
    +
    + goto done;
    + }
    +
    + len = read(devurandom_fd,
    + devurandom_buffer + devurandom_len,
    + need);
    +
    + if (len > 0) {
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: Got %d bytes.\n",len));
    +
    + devurandom_len += len;
    + retry++;
    +
    + } else if (-1 == len) {
    + int err UNUSED_VAROK = errno;
    +
    + DPRINT(Debug,14,(&Debug,
    + "left_part_from_devurandom: read %s (fd=%d): %s (errno=%d)\n",
    + DEVURANDOM,devurandom_fd,
    + strerror(err),err));
    + goto done;
    +
    + } else if (0 == len) {
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: Got EOF.\n"));
    + retry++;
    + close_devurandom();
    + } else {
    + goto done;
    + }
    +
    + } else {
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: have data %d bytes on devurandom buffer, but buffer is %zu bytes\n",
    + devurandom_len,sizeof devurandom_buffer));
    +
    + devurandom_used = buffer_bad;
    + goto done;
    + }
    + break;
    +
    + case buffer_used: {
    + static unsigned char newrandom[DEVURANDOM_LEN];
    + int len;
    +
    + /* Buffer data is used, read new data and check that it differ
    + from used data */
    +
    + if (-1 == devurandom_fd &&
    + ! open_devurandom()) {
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: devurandom is not open.\n"));
    +
    + goto done;
    + }
    +
    + len = read(devurandom_fd,newrandom,sizeof newrandom);
    +
    + if (len > 0) {
    + int i;
    + int differ = 0;
    +
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: Got %d bytes.\n",len));
    +
    + for (i = 0;
    + i < len && i < sizeof newrandom &&
    + i < devurandom_len && i < sizeof devurandom_buffer;
    + i++) {
    + if (newrandom[i] != devurandom_buffer[i])
    + differ++;
    + }
    +
    + if (differ) {
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: %d bytes differ from previous devurandom context\n",
    + differ));
    +
    + if (len < sizeof devurandom_buffer) {
    + memcpy(devurandom_buffer,newrandom,len);
    + devurandom_len = len;
    + } else {
    + memcpy(devurandom_buffer,newrandom,sizeof devurandom_buffer);
    + devurandom_len = sizeof devurandom_buffer;
    + }
    +
    + devurandom_used = buffer_initialized;
    + retry++;
    + } else {
    + DPRINT(Debug,14, (&Debug,
    + "left_part_from_devurandom: Context does not differ from preivious devurandom_buffer\n"));
    + goto done;
    + }
    +
    + } else if(-1 == len) {
    + int err UNUSED_VAROK = errno;
    +
    + DPRINT(Debug,14,(&Debug,
    + "left_part_from_devurandom: read %s (fd=%d): %s (errno=%d)\n",
    + DEVURANDOM,devurandom_fd,
    + strerror(err),err));

    [continued in next message]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)