int check_login_delay (char *username) { time_t now, prev_time; DBM_FILE db; DBM_DATUM key, data; char text[64], *p; int rc; if (login_delay == 0) return 0; time (&now); if (open_stat_db (&db, MU_STREAM_RDWR)) return 0; memset (&key, 0, sizeof key); MU_DATUM_PTR(key) = username; MU_DATUM_SIZE(key) = strlen (username); memset (&data, 0, sizeof data); rc = mu_dbm_fetch (db, key, &data); if (rc) { mu_diag_output (MU_DIAG_ERROR, _("cannot fetch login delay data: %s"), mu_strerror (rc)); mu_dbm_close (db); return 0; } if (MU_DATUM_SIZE(data) > sizeof (text) - 1) { mu_diag_output (MU_DIAG_ERROR, _("invalid entry for '%s': wrong timestamp size"), username); mu_dbm_close (db); return 0; } memcpy (text, MU_DATUM_PTR(data), MU_DATUM_SIZE(data)); text[MU_DATUM_SIZE(data)] = 0; mu_dbm_close (db); prev_time = strtoul (text, &p, 0); if (*p) { mu_diag_output (MU_DIAG_ERROR, _("malformed timestamp for '%s': %s"), username, text); return 0; } return now - prev_time < login_delay; }
static int open_stat_db (DBM_FILE *db, int mode) { int rc = mu_dbm_open (login_stat_file, db, mode, 0660); if (rc) { if (rc == -1) mu_diag_output (MU_DIAG_INFO, _("bad permissions on statistics db")); else mu_diag_output (MU_DIAG_ERROR, _("unable to open statistics db: %s"), mu_strerror (rc)); } return rc; }
static void check_input_err (int rc, size_t sz) { if (rc) { const char *p = mu_stream_strerror (iostream, rc); if (!p) p = mu_strerror (rc); mu_diag_output (MU_DIAG_INFO, _("error reading from input file: %s"), p); imap4d_bye (ERR_NO_IFILE); } else if (sz == 0) { mu_diag_output (MU_DIAG_INFO, _("unexpected eof on input")); imap4d_bye (ERR_NO_IFILE); } }
int imap4d_session_setup (char *username) { auth_data = mu_get_auth_by_name (username); if (auth_data == NULL) { mu_diag_output (MU_DIAG_INFO, _("user `%s' nonexistent"), username); return 1; } return imap4d_session_setup0 (); }
static int cb_tls_required (void *data, mu_config_value_t *val) { int bv; if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) return 1; if (mu_cfg_parse_boolean (val->v.string, &bv)) mu_error (_("Not a boolean value")); else if (bv) { tls_mode = tls_required; mu_diag_output (MU_DIAG_WARNING, "the \"tls-required\" statement is deprecated, " "use \"tls required\" instead"); } else mu_diag_output (MU_DIAG_WARNING, "the \"tls-required\" statement is deprecated, " "use \"tls\" instead"); return 0; }
int imap4d_session_setup0 () { real_homedir = mu_normalize_path (mu_strdup (auth_data->dir)); if (imap4d_check_home_dir (real_homedir, auth_data->uid, auth_data->gid)) return 1; if (modify_homedir) { int rc; mu_vartab_t vtab; char *expr = mu_tilde_expansion (modify_homedir, "/", real_homedir); mu_vartab_create (&vtab); mu_vartab_define (vtab, "user", auth_data->name, 0); mu_vartab_define (vtab, "home", real_homedir, 0); rc = mu_vartab_expand (vtab, expr, &imap4d_homedir); mu_vartab_destroy (&vtab); free (expr); if (rc) { free (real_homedir); mu_diag_funcall (MU_DIAG_ERROR, "mu_vartab_expand", modify_homedir, rc); return 1; } } else imap4d_homedir = strdup (real_homedir); if (strcmp (imap4d_homedir, real_homedir) && imap4d_check_home_dir (imap4d_homedir, auth_data->uid, auth_data->gid)) { free (imap4d_homedir); free (real_homedir); return 1; } if (auth_data->change_uid) setuid (auth_data->uid); util_chdir (imap4d_homedir); namespace_init_session (imap4d_homedir); mu_diag_output (MU_DIAG_INFO, _("user `%s' logged in (source: %s)"), auth_data->name, auth_data->source); return 0; }
int pop3d_get_client_address (int fd, struct sockaddr_in *pcs) { mu_diag_output (MU_DIAG_INFO, _("incoming connection opened")); /* log information on the connecting client. */ if (debug_mode) { mu_diag_output (MU_DIAG_INFO, _("started in debugging mode")); return 1; } else { socklen_t len = sizeof *pcs; if (getpeername (fd, (struct sockaddr*) pcs, &len) < 0) { mu_diag_output (MU_DIAG_ERROR, _("cannot obtain IP address of client: %s"), strerror (errno)); return 1; } } return 0; }
/* Wait TIMEOUT seconds for data on the input stream. Returns 0 if no data available 1 if some data is available -1 an error occurred */ int io_wait_input (int timeout) { int wflags = MU_STREAM_READY_RD; struct timeval tv; int status; tv.tv_sec = timeout; tv.tv_usec = 0; status = mu_stream_wait (iostream, &wflags, &tv); if (status) { mu_diag_output (MU_DIAG_ERROR, _("cannot poll input stream: %s"), mu_strerror(status)); return -1; } return wflags & MU_STREAM_READY_RD; }
static int mbox_is_updated (mu_mailbox_t mailbox) { mu_off_t size = 0; mbox_data_t mud = mailbox->data; if (mu_stream_size (mailbox->stream, &size) != 0) return 1; if (size < mud->size) { mu_observable_notify (mailbox->observable, MU_EVT_MAILBOX_CORRUPT, mailbox); /* And be verbose. ? */ mu_diag_output (MU_DIAG_EMERG, _("mailbox corrupted, shrank in size")); /* FIXME: should I crash. */ return 0; } return (mud->size == size); }
static int imap4d_mainloop (int fd, FILE *infile, FILE *outfile) { imap4d_tokbuf_t tokp; char *text; int debug_mode = isatty (fd); imap4d_child_signal_setup (imap4d_child_signal); util_setio (infile, outfile); if (imap4d_preauth_setup (fd) == 0) { if (debug_mode) { mu_diag_output (MU_DIAG_INFO, _("started in debugging mode")); text = "IMAP4rev1 Debugging mode"; } else text = "IMAP4rev1"; } else { util_flush_output (); return 0; } /* Greetings. */ util_out ((state == STATE_AUTH) ? RESP_PREAUTH : RESP_OK, "%s", text); util_flush_output (); tokp = imap4d_tokbuf_init (); while (1) { imap4d_readline (tokp); /* check for updates */ imap4d_sync (); util_do_command (tokp); imap4d_sync (); util_flush_output (); } return 0; }
int imap4d_init_tls_server () { mu_stream_t tlsstream, stream[2]; int rc; rc = mu_stream_ioctl (iostream, MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_GET, stream); if (rc) { mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM", mu_stream_strerror (iostream, rc)); return 1; } rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0); if (rc) { mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"), mu_stream_strerror (tlsstream, rc)); return 1; } mu_stream_unref (stream[0]); mu_stream_unref (stream[1]); stream[0] = stream[1] = tlsstream; rc = mu_stream_ioctl (iostream, MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_SET, stream); if (rc) { mu_error (_("%s failed: %s"), "MU_IOCTL_SET_STREAM", mu_stream_strerror (iostream, rc)); imap4d_bye (ERR_STREAM_CREATE); } mu_stream_unref (stream[0]); mu_stream_unref (stream[1]); return 0; }
static int _mu_conn_setup (LDAP **pld) { int rc; LDAPURLDesc *ludlist, **ludp; char **urls = NULL; int nurls = 0; char *ldapuri = NULL; LDAP *ld = NULL; int protocol = LDAP_VERSION3; /* FIXME: must be configurable */ if (ldap_param.debug) { if (ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &ldap_param.debug) != LBER_OPT_SUCCESS ) mu_error (_("cannot set LBER_OPT_DEBUG_LEVEL %d"), ldap_param.debug); if (ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_param.debug) != LDAP_OPT_SUCCESS ) mu_error (_("could not set LDAP_OPT_DEBUG_LEVEL %d"), ldap_param.debug); } if (ldap_param.url) { rc = ldap_url_parse (ldap_param.url, &ludlist); if (rc != LDAP_URL_SUCCESS) { mu_error (_("cannot parse LDAP URL(s)=%s (%d)"), ldap_param.url, rc); return 1; } for (ludp = &ludlist; *ludp; ) { LDAPURLDesc *lud = *ludp; char **tmp; if (lud->lud_dn && lud->lud_dn[0] && (lud->lud_host == NULL || lud->lud_host[0] == '\0')) { /* if no host but a DN is provided, try DNS SRV to gather the host list */ char *domain = NULL, *hostlist = NULL; size_t i; struct mu_wordsplit ws; if (ldap_dn2domain (lud->lud_dn, &domain) || !domain) { mu_error (_("DNS SRV: cannot convert DN=\"%s\" into a domain"), lud->lud_dn ); goto dnssrv_free; } rc = ldap_domain2hostlist (domain, &hostlist); if (rc) { mu_error (_("DNS SRV: cannot convert domain=%s into a hostlist"), domain); goto dnssrv_free; } if (mu_wordsplit (hostlist, &ws, MU_WRDSF_DEFFLAGS)) { mu_error (_("DNS SRV: could not parse hostlist=\"%s\": %s"), hostlist, mu_wordsplit_strerror (&ws)); goto dnssrv_free; } tmp = realloc (urls, sizeof(char *) * (nurls + ws.ws_wordc + 1)); if (!tmp) { mu_error ("DNS SRV %s", mu_strerror (errno)); goto dnssrv_free; } urls = tmp; urls[nurls] = NULL; for (i = 0; i < ws.ws_wordc; i++) { urls[nurls + i + 1] = NULL; rc = mu_asprintf (&urls[nurls + i], "%s://%s", lud->lud_scheme, ws.ws_wordv[i]); if (rc) { mu_error ("DNS SRV %s", mu_strerror (rc)); goto dnssrv_free; } } nurls += i; dnssrv_free: mu_wordsplit_free (&ws); ber_memfree (hostlist); ber_memfree (domain); } else { tmp = realloc (urls, sizeof(char *) * (nurls + 2)); if (!tmp) { mu_error ("DNS SRV %s", mu_strerror (errno)); break; } urls = tmp; urls[nurls + 1] = NULL; urls[nurls] = ldap_url_desc2str (lud); if (!urls[nurls]) { mu_error ("DNS SRV %s", mu_strerror (errno)); break; } nurls++; } *ludp = lud->lud_next; lud->lud_next = NULL; ldap_free_urldesc (lud); } if (ludlist) { ldap_free_urldesc (ludlist); return 1; } else if (!urls) return 1; rc = mu_argcv_string (nurls, urls, &ldapuri); if (rc) { mu_error ("%s", mu_strerror (rc)); return 1; } ber_memvfree ((void **)urls); } mu_diag_output (MU_DIAG_INFO, "constructed LDAP URI: %s", ldapuri ? ldapuri : "<DEFAULT>"); rc = ldap_initialize (&ld, ldapuri); if (rc != LDAP_SUCCESS) { mu_error (_("cannot create LDAP session handle for URI=%s (%d): %s"), ldapuri, rc, ldap_err2string (rc)); free (ldapuri); return 1; } free (ldapuri); ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &protocol); if (ldap_param.tls) { rc = ldap_start_tls_s (ld, NULL, NULL); if (rc != LDAP_SUCCESS) { char *msg = NULL; ldap_get_option (ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg); mu_error (_("ldap_start_tls failed: %s"), ldap_err2string (rc)); mu_error (_("TLS diagnostics: %s"), msg); ldap_memfree (msg); ldap_unbind_ext (ld, NULL, NULL); return 1; } } /* FIXME: Timeouts, SASL, etc. */ *pld = ld; return 0; }
/* FIXME: How do we do this ??????: IF a new mailbox is created with the same name as a mailbox which was deleted, its unique identifiers MUST be greater than any unique identifiers used in the previous incarnation of the mailbox. */ int imap4d_create (struct imap4d_session *session, struct imap4d_command *command, imap4d_tokbuf_t tok) { char *name; int isdir = 0; int ns; int rc = RESP_OK; const char *msg = "Completed"; if (imap4d_tokbuf_argc (tok) != 3) return io_completion_response (command, RESP_BAD, "Invalid arguments"); name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1); if (*name == '\0') return io_completion_response (command, RESP_BAD, "Too few arguments"); /* Creating, "Inbox" should always fail. */ if (mu_c_strcasecmp (name, "INBOX") == 0) return io_completion_response (command, RESP_BAD, "Already exist"); /* RFC 3501: If the mailbox name is suffixed with the server's hierarchy separator character, this is a declaration that the client intends to create mailbox names under this name in the hierarchy. The trailing delimiter will be removed by namespace normalizer, so test for it now. */ if (name[strlen (name) - 1] == MU_HIERARCHY_DELIMITER) isdir = 1; /* Allocates memory. */ name = namespace_getfullpath (name, &ns); if (!name) return io_completion_response (command, RESP_NO, "Cannot create mailbox"); /* It will fail if the mailbox already exists. */ if (access (name, F_OK) != 0) { if (make_interdir (name, MU_HIERARCHY_DELIMITER, MKDIR_PERMISSIONS)) { rc = RESP_NO; msg = "Cannot create mailbox"; } if (rc == RESP_OK && !isdir) { mu_mailbox_t mbox; rc = mu_mailbox_create_default (&mbox, name); if (rc) { mu_diag_output (MU_DIAG_ERR, _("Cannot create mailbox %s: %s"), name, mu_strerror (rc)); rc = RESP_NO; msg = "Cannot create mailbox"; } else if ((rc = mu_mailbox_open (mbox, MU_STREAM_RDWR | MU_STREAM_CREAT | mailbox_mode[ns]))) { mu_diag_output (MU_DIAG_ERR, _("Cannot open mailbox %s: %s"), name, mu_strerror (rc)); rc = RESP_NO; msg = "Cannot create mailbox"; } else { mu_mailbox_close (mbox); mu_mailbox_destroy (&mbox); rc = RESP_OK; } } } else { rc = RESP_NO; msg = "already exists"; } return io_completion_response (command, rc, "%s", msg); }