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)