dns_address * dns_address_from_rr(dns_answer *dnsa, dns_record *rr) { dns_address * yield = NULL; uschar * dnsa_lim = dnsa->answer + dnsa->answerlen; if (rr->type == T_A) { uschar *p = US rr->data; if (p + 4 <= dnsa_lim) { yield = store_get(sizeof(dns_address) + 20); (void)sprintf(CS yield->address, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); yield->next = NULL; } } #if HAVE_IPV6 else { if (rr->data + 16 <= dnsa_lim) { yield = store_get(sizeof(dns_address) + 50); inet_ntop(AF_INET6, US rr->data, CS yield->address, 50); yield->next = NULL; } } #endif /* HAVE_IPV6 */ return yield; }
dns_address * dns_address_from_rr(dns_answer *dnsa, dns_record *rr) { dns_address *yield = NULL; dnsa = dnsa; /* Stop picky compilers warning */ if (rr->type == T_A) { uschar *p = (uschar *)(rr->data); yield = store_get(sizeof(dns_address) + 20); (void)sprintf(CS yield->address, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); yield->next = NULL; } #if HAVE_IPV6 else { yield = store_get(sizeof(dns_address) + 50); inet_ntop(AF_INET6, (uschar *)(rr->data), CS yield->address, 50); yield->next = NULL; } #endif /* HAVE_IPV6 */ return yield; }
int tls_import_cert(const uschar * buf, void ** cert) { void * reset_point = store_get(0); gnutls_datum_t datum; gnutls_x509_crt_t crt = *(gnutls_x509_crt_t *)cert; int fail = 0; if (crt) gnutls_x509_crt_deinit(crt); else gnutls_global_init(); gnutls_x509_crt_init(&crt); datum.data = string_unprinting(US buf); datum.size = Ustrlen(datum.data); if ((fail = gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM))) { log_write(0, LOG_MAIN, "TLS error in certificate import: %s", gnutls_strerror(fail)); fail = 1; } else *cert = (void *)crt; store_reset(reset_point); return fail; }
static void * json_malloc(size_t nbytes) { void * p = store_get((int)nbytes); /* debug_printf("%s %d: %p\n", __FUNCTION__, (int)nbytes, p); */ return p; }
static pcre_list * compile(const uschar * list) { int sep = 0; uschar *regex_string; const char *pcre_error; int pcre_erroffset; pcre_list *re_list_head = NULL; pcre_list *ri; /* precompile our regexes */ while ((regex_string = string_nextinlist(&list, &sep, NULL, 0))) if (strcmpic(regex_string, US"false") != 0 && Ustrcmp(regex_string, "0") != 0) { pcre *re; /* compile our regular expression */ if (!(re = pcre_compile( CS regex_string, 0, &pcre_error, &pcre_erroffset, NULL ))) { log_write(0, LOG_MAIN, "regex acl condition warning - error in regex '%s': %s at offset %d, skipped.", regex_string, pcre_error, pcre_erroffset); continue; } ri = store_get(sizeof(pcre_list)); ri->re = re; ri->pcre_text = regex_string; ri->next = re_list_head; re_list_head = ri; } return re_list_head; }
LONG_DOUBLE eval_expr_binop(eval_context *ctx, ast_node *tree) { expr_binop_data *binop_data = (expr_binop_data*)tree->data; switch (binop_data->op) { case OP_ADD: return eval_expr(ctx, binop_data->lhs) + eval_expr(ctx, binop_data->rhs); case OP_SUB: return eval_expr(ctx, binop_data->lhs) - eval_expr(ctx, binop_data->rhs); case OP_MUL: return eval_expr(ctx, binop_data->lhs) * eval_expr(ctx, binop_data->rhs); case OP_DIV: return eval_expr(ctx, binop_data->lhs) / eval_expr(ctx, binop_data->rhs); case OP_MOD: { // Knuthsche "floored division" LONG_DOUBLE a = eval_expr(ctx, binop_data->lhs); LONG_DOUBLE n = eval_expr(ctx, binop_data->rhs); return a-n*floor(a/n); } case OP_EXP: return pow(eval_expr(ctx, binop_data->lhs), eval_expr(ctx, binop_data->rhs)); case OP_ASS: { if (binop_data->lhs->type != EXPR_VAR) return eval_emit_error(ctx, "Cannot assign to a non-variable."); else { expr_var_data *var_data = (expr_var_data*)binop_data->lhs->data; LONG_DOUBLE rhs_res = eval_expr(ctx, binop_data->rhs); store_var(store_get(), var_data->name, rhs_res); return rhs_res; } } default: return eval_emit_error(ctx, "Operator not implemented."); } }
static uschar * pdkim_decode_qp(uschar * str) { int nchar = 0; uschar * q; uschar * p = str; uschar * n = store_get(Ustrlen(str)+1); *n = '\0'; q = n; while (*p) { if (*p == '=') { p = pdkim_decode_qp_char(p, &nchar); if (nchar >= 0) { *q++ = nchar; continue; } } else *q++ = *p; p++; } *q = '\0'; return n; }
static BOOL read_nonrecipients_tree(tree_node **connect, FILE *f, uschar *buffer, int buffer_size) { tree_node *node; int n = Ustrlen(buffer); BOOL right = buffer[1] == 'Y'; if (n < 5) return FALSE; /* malformed line */ buffer[n-1] = 0; /* Remove \n */ node = store_get(sizeof(tree_node) + n - 3); *connect = node; Ustrcpy(node->name, buffer + 3); node->data.ptr = NULL; if (buffer[0] == 'Y') { if (Ufgets(buffer, buffer_size, f) == NULL || !read_nonrecipients_tree(&node->left, f, buffer, buffer_size)) return FALSE; } else node->left = NULL; if (right) { if (Ufgets(buffer, buffer_size, f) == NULL || !read_nonrecipients_tree(&node->right, f, buffer, buffer_size)) return FALSE; } else node->right = NULL; (void) count_below(*connect); return TRUE; }
uschar * string_localpart_alabel_to_utf8(const uschar * alabel, uschar ** err) { size_t p_len = Ustrlen(alabel); punycode_uint * p; uschar * s; uschar * res; int rc; if (alabel[0] != 'x' || alabel[1] != 'n' || alabel[2] != '-' || alabel[3] != '-') { if (err) *err = US"bad alabel prefix"; return NULL; } p_len -= 4; p = (punycode_uint *) store_get((p_len+1) * sizeof(*p)); if ((rc = punycode_decode(p_len, CCS alabel+4, &p_len, p, NULL)) != PUNYCODE_SUCCESS) { if (err) *err = US punycode_strerror(rc); return NULL; } s = US stringprep_ucs4_to_utf8(p, p_len, NULL, &p_len); res = string_copyn(s, p_len); free(s); return res; }
uschar * auth_xtextencode(uschar *clear, int len) { uschar *code; uschar *p = (uschar *)clear; uschar *pp; int c = len; int count = 1; register int x; /* We have to do a prepass to find out how many specials there are, in order to get the right amount of store. */ while (c -- > 0) count += ((x = *p++) < 33 || x > 127 || x == '+' || x == '=')? 3 : 1; pp = code = store_get(count); p = (uschar *)clear; c = len; while (c-- > 0) { if ((x = *p++) < 33 || x > 127 || x == '+' || x == '=') { sprintf(CS pp, "+%.02x", x); /* There's always room */ pp += 3; } else *pp++ = x; } *pp = 0; return code; }
uschar * tls_cert_ext_by_oid(void * cert, uschar * oid, int idx) { uschar * cp1 = NULL; uschar * cp2; uschar * cp3; size_t siz = 0; unsigned int crit; int ret; ret = gnutls_x509_crt_get_extension_by_oid ((gnutls_x509_crt_t)cert, oid, idx, cp1, &siz, &crit); if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) return g_err("ge0", __FUNCTION__, ret); cp1 = store_get(siz*4 + 1); ret = gnutls_x509_crt_get_extension_by_oid ((gnutls_x509_crt_t)cert, oid, idx, cp1, &siz, &crit); if (ret < 0) return g_err("ge1", __FUNCTION__, ret); /* binary data, DER encoded */ /* just dump for now */ for(cp3 = cp2 = cp1+siz; cp1 < cp2; cp3 += 3, cp1++) sprintf(cp3, "%.2x ", *cp1); cp3[-1]= '\0'; return cp2; }
uschar * string_copy_dnsdomain(uschar *s) { uschar *yield; uschar *ss = yield = store_get(Ustrlen(s) + 1); while (*s != 0) { if (*s != '\\') { *ss++ = *s++; } else if (isdigit(s[1])) { *ss++ = (s[1] - '0')*100 + (s[2] - '0')*10 + s[3] - '0'; s += 4; } else if (*(++s) != 0) { *ss++ = *s++; } } *ss = 0; return yield; }
static void headersAction(Widget w, XtPointer client_data, XtPointer call_data) { uschar buffer[256]; header_line *h, *next; Widget text = text_create(US client_data, text_depth); void *reset_point; w = w; /* Keep picky compilers happy */ call_data = call_data; /* Remember the point in the dynamic store so we can recover to it afterwards. Then use Exim's function to read the header. */ reset_point = store_get(0); sprintf(CS buffer, "%s-H", US client_data); if (spool_read_header(buffer, TRUE, FALSE) != spool_read_OK) { if (errno == ERRNO_SPOOLFORMAT) { struct stat statbuf; sprintf(CS big_buffer, "%s/input/%s", spool_directory, buffer); if (Ustat(big_buffer, &statbuf) == 0) text_showf(text, "Format error in spool file %s: size=%d\n", buffer, statbuf.st_size); else text_showf(text, "Format error in spool file %s\n", buffer); } else text_showf(text, "Read error for spool file %s\n", buffer); store_reset(reset_point); return; } if (sender_address != NULL) { text_showf(text, "%s sender: <%s>\n", f.sender_local ? "Local" : "Remote", sender_address); } if (recipients_list != NULL) { int i; text_show(text, US"Recipients:\n"); for (i = 0; i < recipients_count; i++) { text_showf(text, " %s %s\n", (tree_search(tree_nonrecipients, recipients_list[i].address) == NULL)? " ":"*", recipients_list[i].address); } text_show(text, US"\n"); } for (h = header_list; h != NULL; h = next) { next = h->next; text_showf(text, "%c ", h->type); /* Don't push h->text through a %s */ text_show(text, h->text); /* expansion as it may be v large */ } store_reset(reset_point); }
static int rfc2047_qpdecode(uschar *string, uschar **ptrptr) { int len = 0; uschar *ptr; ptr = *ptrptr = store_get(Ustrlen(string) + 1); /* No longer than this */ while (*string != 0) { int ch = *string++; if (ch == '_') *ptr++ = ' '; else if (ch == '=') { int a = *string; int b = (a == 0)? 0 : string[1]; if (!isxdigit(a) || !isxdigit(b)) return -1; /* Bad QP string */ *ptr++ = ((Ustrchr(hex_digits, tolower(a)) - hex_digits) << 4) + Ustrchr(hex_digits, tolower(b)) - hex_digits; string += 2; } else if (ch == ' ' || ch == '\t') return -1; /* Whitespace is illegal */ else *ptr++ = ch; len++; } *ptr = 0; return len; }
uschar * string_localpart_utf8_to_alabel(const uschar * utf8, uschar ** err) { size_t ucs4_len; punycode_uint * p; size_t p_len; uschar * res; int rc; if (!string_is_utf8(utf8)) return string_copy(utf8); p = (punycode_uint *) stringprep_utf8_to_ucs4(CCS utf8, -1, &ucs4_len); p_len = ucs4_len*4; /* this multiplier is pure guesswork */ res = store_get(p_len+5); res[0] = 'x'; res[1] = 'n'; res[2] = res[3] = '-'; if ((rc = punycode_encode(ucs4_len, p, NULL, &p_len, CS res+4)) != PUNYCODE_SUCCESS) { DEBUG(D_expand) debug_printf("l_u2a: bad '%s'\n", punycode_strerror(rc)); free(p); if (err) *err = US punycode_strerror(rc); return NULL; } p_len += 4; free(p); res[p_len] = '\0'; return res; }
uschar * string_copyn(const uschar *s, int n) { uschar *ss = store_get(n + 1); Ustrncpy(ss, s, n); ss[n] = 0; return ss; }
void tree_add_nonrecipient(uschar *s) { tree_node *node = store_get(sizeof(tree_node) + Ustrlen(s)); Ustrcpy(node->name, s); node->data.ptr = NULL; if (!tree_insertnode(&tree_nonrecipients, node)) store_reset(node); }
uschar * string_copy(const uschar *s) { int len = Ustrlen(s) + 1; uschar *ss = store_get(len); memcpy(ss, s, len); return ss; }
void tree_add_duplicate(uschar *s, address_item *addr) { tree_node *node = store_get(sizeof(tree_node) + Ustrlen(s)); Ustrcpy(node->name, s); node->data.ptr = addr; if (!tree_insertnode(&tree_duplicates, node)) store_reset(node); }
uschar * string_copylc(const uschar *s) { uschar *ss = store_get(Ustrlen(s) + 1); uschar *p = ss; while (*s != 0) *p++ = tolower(*s++); *p = 0; return ss; }
uschar * string_copynlc(uschar *s, int n) { uschar *ss = store_get(n + 1); uschar *p = ss; while (n-- > 0) *p++ = tolower(*s++); *p = 0; return ss; }
ip_address_item * os_common_find_running_interfaces(void) { ip_address_item *yield = store_get(sizeof(address_item)); yield->address = US"127.0.0.1"; yield->port = 0; yield->next = NULL; #if HAVE_IPV6 yield->next = store_get(sizeof(address_item)); yield->next->address = US"::1"; yield->next->port = 0; yield->next->next = NULL; #endif DEBUG(D_interface) debug_printf("Unable to find local interface addresses " "on this OS: returning loopback address(es)\n"); return yield; }
static pdkim_stringlist * pdkim_prepend_stringlist(pdkim_stringlist * base, const uschar * str) { pdkim_stringlist * new_entry = store_get(sizeof(pdkim_stringlist)); memset(new_entry, 0, sizeof(pdkim_stringlist)); new_entry->value = string_copy(str); if (base) new_entry->next = base; return new_entry; }
void tree_add_unusable(host_item *h) { tree_node *node; uschar s[256]; sprintf(CS s, "T:%.200s:%s", h->name, h->address); node = store_get(sizeof(tree_node) + Ustrlen(s)); Ustrcpy(node->name, s); node->data.val = h->why; if (h->status == hstatus_unusable_expired) node->data.val += 256; if (!tree_insertnode(&tree_unusable, node)) store_reset(node); }
uschar * string_dequote(const uschar **sptr) { const uschar *s = *sptr; uschar *t, *yield; /* First find the end of the string */ if (*s != '\"') { while (*s != 0 && !isspace(*s)) s++; } else { s++; while (*s != 0 && *s != '\"') { if (*s == '\\') (void)string_interpret_escape(&s); s++; } if (*s != 0) s++; } /* Get enough store to copy into */ t = yield = store_get(s - *sptr + 1); s = *sptr; /* Do the copy */ if (*s != '\"') { while (*s != 0 && !isspace(*s)) *t++ = *s++; } else { s++; while (*s != 0 && *s != '\"') { if (*s == '\\') *t++ = string_interpret_escape(&s); else *t++ = *s; s++; } if (*s != 0) s++; } /* Update the pointer and return the terminated copy */ *sptr = s; *t = 0; return yield; }
static BOOL rda_read_string(int fd, uschar **sp) { int len; if (read(fd, &len, sizeof(int)) != sizeof(int)) return FALSE; if (len == 0) *sp = NULL; else { *sp = store_get(len); if (read(fd, *sp, len) != len) return FALSE; } return TRUE; }
uschar * string_unprinting(uschar *s) { uschar *p, *q, *r, *ss; int len, off; p = Ustrchr(s, '\\'); if (!p) return s; len = Ustrlen(s) + 1; ss = store_get(len); q = ss; off = p - s; if (off) { memcpy(q, s, off); q += off; } while (*p) { if (*p == '\\') { *q++ = string_interpret_escape((const uschar **)&p); p++; } else { r = Ustrchr(p, '\\'); if (!r) { off = Ustrlen(p); memcpy(q, p, off); p += off; q += off; break; } else { off = r - p; memcpy(q, p, off); q += off; p = r; } } } *q = '\0'; return ss; }
/* * Given a C string, make sure it's safe to pass to a * printf-style function ('%' chars are escaped by doubling * them up. Optionally, also make sure the string ends with a '\n' */ static char *get_format_string(char *str, int need_newline) { char *p; char *q; char *newstr; int percent_count; int len; /* Count number of '%' characters in string, and get the total length while at it */ for (p = str, percent_count = 0; *p; p++) if (*p == '%') percent_count++; len = p - str; /* Decide if we need a newline added */ if (need_newline) { if (len && (*(p-1) == '\n')) need_newline = 0; else need_newline = 1; /* paranoia - just in case something other than 1 was used to indicate truth */ } /* If it's all good, just return the string we were passed */ if ((!percent_count) && (!need_newline)) return str; /* Gotta make a new string, with '%'s and/or '\n' added */ newstr = store_get(len + percent_count + need_newline + 1); for (p = str, q = newstr; *p; p++, q++) { *q = *p; if (*q == '%') { q++; *q = '%'; } } if (need_newline) { *q = '\n'; q++; } *q = 0; return newstr; }
ip_address_item * os_common_find_running_interfaces(void) { struct ifaddrs *ifalist = NULL; ip_address_item *yield = NULL; ip_address_item *last = NULL; ip_address_item *next; if (getifaddrs(&ifalist) != 0) log_write(0, LOG_PANIC_DIE, "Unable to call getifaddrs: %d %s", errno, strerror(errno)); struct ifaddrs *ifa; for (ifa = ifalist; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != AF_INET #if HAVE_IPV6 && ifa->ifa_addr->sa_family != AF_INET6 #endif /* HAVE_IPV6 */ ) continue; if ( !(ifa->ifa_flags & IFF_UP) ) /* Only want 'UP' interfaces */ continue; /* Create a data block for the address, fill in the data, and put it on the chain. */ next = store_get(sizeof(ip_address_item)); next->next = NULL; next->port = 0; (void)host_ntoa(-1, ifa->ifa_addr, next->address, NULL); if (yield == NULL) yield = last = next; else { last->next = next; last = next; } DEBUG(D_interface) debug_printf("Actual local interface address is %s (%s)\n", last->address, ifa->ifa_name); } /* free the list of addresses, and return the chain of data blocks. */ freeifaddrs (ifalist); return yield; }
void rf_change_domain(address_item *addr, uschar *domain, BOOL rewrite, address_item **addr_new) { address_item *parent = store_get(sizeof(address_item)); uschar *at = Ustrrchr(addr->address, '@'); uschar *address = string_sprintf("%.*s@%s", at - addr->address, addr->address, domain); DEBUG(D_route) debug_printf("domain changed to %s\n", domain); /* The current address item is made into the parent, and a new address is set up in the old space. */ *parent = *addr; /* First copy in initializing values, to wipe out stuff such as the named domain cache. Then copy over the propagating fields from the parent. Then set up the new fields. */ *addr = address_defaults; addr->p = parent->p; addr->address = address; addr->unique = string_copy(address); addr->parent = parent; addr->next = *addr_new; *addr_new = addr; /* Rewrite header lines if requested */ if (rewrite) { header_line *h; DEBUG(D_route|D_rewrite) debug_printf("rewriting header lines\n"); for (h = header_list; h != NULL; h = h->next) { header_line *newh = rewrite_header(h, parent->domain, domain, global_rewrite_rules, rewrite_existflags, TRUE); if (newh != NULL) { h = newh; header_rewritten = TRUE; } } } }