int mu_tcp_stream_create_with_source_host (mu_stream_t *stream, const char *host, unsigned port, const char *source_host, int flags) { int rc; struct mu_sockaddr *remote_addr, *source_addr = NULL; struct mu_sockaddr_hints hints; memset (&hints, 0, sizeof hints); hints.family = AF_INET; hints.socktype = SOCK_STREAM; hints.port = port; rc = mu_sockaddr_from_node (&remote_addr, host, NULL, &hints); if (rc) return rc; if (source_host) { hints.flags = MU_AH_PASSIVE; hints.port = 0; rc = mu_sockaddr_from_node (&source_addr, source_host, NULL, &hints); if (rc) { mu_sockaddr_free (remote_addr); return 0; } } rc = mu_tcp_stream_create_from_sa (stream, remote_addr, source_addr, flags); if (rc && !(rc == EAGAIN || rc == EINPROGRESS)) { mu_sockaddr_free (remote_addr); mu_sockaddr_free (source_addr); } return rc; }
int mu_tcp_stream_create_with_source_ip (mu_stream_t *pstream, const char *host, unsigned port, unsigned long source_ip, int flags) { int rc; struct mu_sockaddr *remote_addr, *source_addr = NULL; struct mu_sockaddr_hints hints; memset (&hints, 0, sizeof hints); hints.family = AF_INET; hints.socktype = SOCK_STREAM; hints.protocol = IPPROTO_TCP; hints.port = port; rc = mu_sockaddr_from_node (&remote_addr, host, NULL, &hints); if (rc) return rc; if (source_ip) { struct sockaddr_in s; s.sin_family = AF_INET; s.sin_addr.s_addr = source_ip; s.sin_port = 0; rc = mu_sockaddr_create (&source_addr, (struct sockaddr*)&s, sizeof (s)); if (rc) { mu_sockaddr_free (remote_addr); return 0; } } rc = mu_tcp_stream_create_from_sa (pstream, remote_addr, source_addr, flags); if (rc && !(rc == EAGAIN || rc == EINPROGRESS)) { mu_sockaddr_free (remote_addr); mu_sockaddr_free (source_addr); } return rc; }
int mutool_acl (int argc, char **argv) { int rc, index; mu_acl_result_t result; mu_cfg_tree_t *tree = NULL, *temp_tree = NULL; mu_cfg_node_t *node; if (argp_parse (&acl_argp, argc, argv, ARGP_IN_ORDER, &index, NULL)) return 1; argc -= index; argv += index; if (argc == 0) { mu_error (_("not enough arguments")); return 1; } if (input_file_name) { mu_load_site_rcfile = 0; mu_load_user_rcfile = 0; mu_load_rcfile = input_file_name; } mu_acl_cfg_init (); if (mu_libcfg_parse_config (&tree)) return 1; if (!tree) return 0; if (mu_cfg_find_node (tree, path, &node)) { mu_error (_("cannot find node: %s"), path); return 1; } mu_cfg_tree_create (&temp_tree); mu_cfg_tree_add_node (temp_tree, node); rc = mu_cfg_tree_reduce (temp_tree, NULL, acl_cfg_param, NULL); if (rc) return 1; if (!acl) { mu_error (_("No ACL found in config")); return 1; } while (argc--) { const char *ap = *argv++; rc = mu_sockaddr_from_node (&target_sa, ap, NULL, NULL); if (rc) { mu_error ("mu_sockaddr_from_node: %s", mu_strerror (rc)); exit (1); } mu_printf ("Testing %s:\n", ap); rc = mu_acl_check_sockaddr (acl, target_sa->addr, target_sa->addrlen, &result); mu_sockaddr_free_list (target_sa); if (rc) { mu_error ("mu_acl_check_sockaddr failed: %s", mu_strerror (rc)); return 1; } switch (result) { case mu_acl_result_undefined: mu_printf ("%s: undefined\n", ap); break; case mu_acl_result_accept: mu_printf ("%s: accept\n", ap); break; case mu_acl_result_deny: mu_printf ("%s: deny\n", ap); break; } } mu_cfg_destroy_tree (&tree); mu_cfg_destroy_tree (&temp_tree); return 0; }
int main (int argc, char **argv) { int i; char *host = NULL; char *infile = NULL; char *port = NULL; int tls = 0; int raw = 1; int flags = 0; mu_stream_t stream; mu_smtp_t smtp; mu_stream_t instr; char *from = NULL; mu_list_t rcpt_list = NULL; mu_list_t meth_list = NULL; mu_list_t skiphdr_list = NULL; struct mu_sockaddr *sa; struct mu_sockaddr_hints hints; mu_set_program_name (argv[0]); mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); if (argc < 2) usage (); memset (&hints, 0, sizeof (hints)); hints.flags = MU_AH_DETECT_FAMILY; hints.port = 25; hints.protocol = IPPROTO_TCP; hints.socktype = SOCK_STREAM; MU_ASSERT (mu_smtp_create (&smtp)); for (i = 1; i < argc; i++) { if (strncmp (argv[i], "port=", 5) == 0) port = argv[i] + 5; else if (strncmp (argv[i], "family=", 7) == 0) { hints.flags &= ~MU_AH_DETECT_FAMILY; switch (argv[i][7]) { case '4': hints.family = AF_INET; break; case '6': hints.family = AF_INET6; break; default: mu_error ("invalid family name: %s", argv[i]+7); exit (1); } } else if (strncmp (argv[i], "trace=", 6) == 0) { char *arg = argv[i] + 6; if (mu_isdigit (arg[0])) mu_smtp_trace (smtp, atoi (argv[i] + 6) ? MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR); else { mu_smtp_trace (smtp, MU_SMTP_TRACE_SET); if (strcmp (arg, "secure") == 0) mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET, MU_XSCRIPT_SECURE); else if (strcmp (arg, "payload") == 0) mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET, MU_XSCRIPT_PAYLOAD); } } else if (strncmp (argv[i], "tls=", 4) == 0) tls = atoi (argv[i] + 4); else if (strncmp (argv[i], "domain=", 7) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN, argv[i] + 7)); else if (strncmp (argv[i], "user="******"pass="******"service=", 8) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_SERVICE, argv[i] + 8)); else if (strncmp (argv[i], "realm=", 6) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_REALM, argv[i] + 6)); else if (strncmp (argv[i], "host=", 5) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_HOST, argv[i] + 5)); else if (strncmp (argv[i], "url=", 4) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_URL, argv[i] + 4)); else if (strncmp (argv[i], "input=", 6) == 0) infile = argv[i] + 6; else if (strncmp (argv[i], "raw=", 4) == 0) raw = atoi (argv[i] + 4); else if (strncmp (argv[i], "rcpt=", 5) == 0) { if (!rcpt_list) MU_ASSERT (mu_list_create (&rcpt_list)); MU_ASSERT (mu_list_append (rcpt_list, argv[i] + 5)); } else if (strncmp (argv[i], "from=", 5) == 0) from = argv[i] + 5; else if (strncmp (argv[i], "auth=", 5) == 0) update_list (&meth_list, argv[i] + 5); else if (strncmp (argv[i], "skiphdr=", 8) == 0) { update_list (&skiphdr_list, argv[i] + 8); raw = 0; } else if (host) { mu_error ("server name already given: %s, new name %s?", host, argv[i]); exit (1); } else host = argv[i]; } if (!host) usage (); if (!raw) flags = MU_STREAM_SEEK; if (infile) MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|flags)); else MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags)); host = argv[1]; MU_ASSERT (mu_sockaddr_from_node (&sa, host, port, &hints)); MU_ASSERT (mu_tcp_stream_create_from_sa (&stream, sa, NULL, MU_STREAM_RDWR)); mu_smtp_set_carrier (smtp, stream); mu_stream_unref (stream); if (!from) { from = getenv ("USER"); if (!from) { mu_error ("cannot determine sender name"); exit (1); } } if (raw && !rcpt_list) { mu_error ("no recipients"); exit (1); } MU_ASSERT (mu_smtp_open (smtp)); MU_ASSERT (mu_smtp_ehlo (smtp)); if (tls && mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0) { MU_ASSERT (mu_smtp_starttls (smtp)); MU_ASSERT (mu_smtp_ehlo (smtp)); } if (meth_list) { int status; MU_ASSERT (mu_smtp_add_auth_mech_list (smtp, meth_list)); status = mu_smtp_auth (smtp); switch (status) { case 0: MU_ASSERT (mu_smtp_ehlo (smtp)); break; case ENOSYS: case MU_ERR_NOENT: /* Ok, skip it */ break; default: mu_error ("authentication failed: %s", mu_strerror (status)); exit (1); } } MU_ASSERT (mu_smtp_mail_basic (smtp, from, NULL)); mu_list_foreach (rcpt_list, send_rcpt_command, smtp); if (raw) { /* Raw sending mode: send from the stream directly */ MU_ASSERT (mu_smtp_send_stream (smtp, instr)); } else { /* Message (standard) sending mode: send a MU message. */ mu_message_t msg; mu_stream_t ostr, bstr; mu_header_t hdr; mu_iterator_t itr; mu_body_t body; if (skiphdr_list) mu_list_set_comparator (skiphdr_list, headercmp); MU_ASSERT (mu_stream_to_message (instr, &msg)); mu_stream_unref (instr); MU_ASSERT (mu_smtp_data (smtp, &ostr)); MU_ASSERT (mu_message_get_header (msg, &hdr)); MU_ASSERT (mu_header_get_iterator (hdr, &itr)); for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) { const char *name; void *value; mu_iterator_current_kv (itr, (void*) &name, &value); if (mu_list_locate (skiphdr_list, (void*) name, NULL) == 0) continue; mu_stream_printf (ostr, "%s: %s\n", name, (char*)value); } mu_iterator_destroy (&itr); MU_ASSERT (mu_stream_write (ostr, "\n", 1, NULL)); MU_ASSERT (mu_message_get_body (msg, &body)); MU_ASSERT (mu_body_get_streamref (body, &bstr)); MU_ASSERT (mu_stream_copy (ostr, bstr, 0, NULL)); mu_stream_destroy (&bstr); mu_stream_close (ostr); mu_stream_destroy (&ostr); } MU_ASSERT (mu_smtp_dot (smtp)); MU_ASSERT (mu_smtp_quit (smtp)); mu_smtp_destroy (&smtp); mu_stream_close (instr); mu_stream_destroy (&instr); return 0; }
int mu_sockaddr_from_url (struct mu_sockaddr **retval, mu_url_t url, struct mu_sockaddr_hints *mh) { int rc; const char *scheme; const char *node = NULL, *serv = NULL; struct mu_sockaddr_hints hints; if (mh) memcpy (&hints, mh, sizeof (hints)); else { memset (&hints, 0, sizeof(hints)); hints.family = AF_UNSPEC; hints.socktype = SOCK_STREAM; hints.protocol = IPPROTO_TCP; } if (hints.family == AF_UNSPEC) { rc = mu_url_sget_scheme (url, &scheme); if (rc) return rc; if (mu_kwd_xlat_name (famtab, scheme, &hints.family)) { if (hints.flags & MU_AH_DETECT_FAMILY) { int flags = 0; mu_url_get_flags (url, &flags); #ifdef MAILUTILS_IPV6 if (flags & MU_URL_IPV6) hints.family = AF_INET6; else #endif if (flags & (MU_URL_HOST|MU_URL_PORT)) hints.family = AF_INET; else if (flags & MU_URL_PATH) hints.family = AF_UNIX; else return MU_ERR_FAMILY; } else return MU_ERR_FAMILY; } } if (hints.family == AF_UNIX) { rc = mu_url_sget_path (url, &node); if (rc) { if (rc == MU_ERR_NOENT) { rc = mu_url_sget_host (url, &node); if (rc == MU_ERR_NOENT) return MU_ERR_NONAME; } if (rc) return rc; } } else { #ifdef MAILUTILS_IPV6 if (hints.family == AF_UNSPEC) hints.family = mu_url_has_flag (url, MU_URL_IPV6) ? AF_INET6 : AF_INET; #endif rc = mu_url_sget_host (url, &node); if (rc && rc != MU_ERR_NOENT) return MU_ERR_NONAME; rc = mu_url_sget_portstr (url, &serv); if (rc && rc != MU_ERR_NOENT) return MU_ERR_NONAME; } return mu_sockaddr_from_node (retval, node, serv, &hints); }