void builtins_init() { assign_global_builtins(builtin_info); stringfuncs_init(); table_init(); iostream_init(); }
int imap_iface_test (iface_t *iface, const char *user, const char *passwd, const char *ca_file, const char *ca_path, const int starttls) { bool plain_auth_avail, starttls_avail; char *errstr; imap_info_t *info = NULL; imap_resp_t *resp = NULL; int state, result; iostream_t *stream; plain_auth_avail = false; starttls_avail = false; if ((stream = iostream_init (&errstr)) == NULL) { ocf_log (LOG_ERR, "%s: iostream_init: %s", __func__, errstr); return IMAP_ERR_SYSTEM; } if ((info = imap_info_alloc (BUFSIZE)) == NULL) { ocf_log (LOG_ERR, "%s: imap_info_alloc: %s", __func__, strerror (errno)); goto failure; } if ((resp = imap_resp_alloc (BUFSIZE)) == NULL) { ocf_log (LOG_ERR, "%s: imap_resp_alloc: %s", __func__, strerror (errno)); goto failure; } /* Connect to defined interface. */ if (iostream_connect (stream, iface->host, iface->port, &errstr) < 0) { ocf_log (LOG_ERR, "%s: iostream_connect: %s", __func__, errstr); goto failure; } if (iface->ssl && iostream_encrypt (stream, ca_file, ca_path, &errstr) < 0) { ocf_log (LOG_ERR, "%s: iostream_encrypt: %s", __func__, errstr); goto failure; } for (state=IMAP_STAT_CONNECT, result=IMAP_SUCCESS; ; ) { if (imap_recv (stream, info, resp) != IMAP_SUCCESS) goto failure; /* error logged by imap_recv */ if (resp->type == IMAP_RESP_TYPE_UNTAGGED && resp->status && strncmp (resp->status, "BYE", 3) == 0) { if (state == IMAP_STAT_LOGOUT) { continue; } else if (resp->extra) { ocf_log (LOG_ERR, "%s: connection terminated by server: %s", __func__, resp->extra); } else { ocf_log (LOG_ERR, "%s: connection terminated by server", __func__); } } else if (state == IMAP_STAT_CONNECT) { if (resp->type == IMAP_RESP_TYPE_UNTAGGED) { if (STRNULLCMP (resp->status, "OK", 2) == 0) { ocf_log (LOG_DEBUG, "%s: connected to %s%s://%s:%s/", __func__, iface->service, iface->ssl ? "s" : "", iface->host, iface->port); state = IMAP_STAT_CAPABILITY; if (imap_send (stream, info, "CAPABILITY") != IMAP_SUCCESS) goto failure; continue; } } } else if (state == IMAP_STAT_CAPABILITY) { if (resp->type == IMAP_RESP_TYPE_UNTAGGED) { if (STRNULLCMP (resp->command, "CAPABILITY", 10) == 0) { if (! plain_auth_avail && strstr (resp->command, "AUTH=PLAIN") != NULL) { ocf_log (LOG_DEBUG, "%s: plain text passwords enabled", __func__); plain_auth_avail = true; } if (! iostream_encrypted (stream) && ! starttls_avail && strstr (resp->command, "STARTTLS") != NULL) { ocf_log (LOG_DEBUG, "%s: connection can be encrypted", __func__); starttls_avail = true; } } continue; } else if (resp->type == IMAP_RESP_TYPE_TAGGED) { if (STRNULLCMP (resp->status, "OK", 2) == 0) { if (! starttls_avail) { ocf_log (LOG_DEBUG, "%s: connection cannot be encrypted", __func__); } /* We don't support password encryption yet, bail if plain text password aren't enabled. */ if (! plain_auth_avail) { ocf_log (LOG_WARNING, "%s: plain text passwords not enabled", __func__); state = IMAP_STAT_LOGOUT; if (imap_send (stream, info, "LOGOUT") < 0) goto failure; } else if (starttls_avail && starttls) { state = IMAP_STAT_STARTTLS; if (imap_send (stream, info, "STARTTLS") < 0) goto failure; } else { state = IMAP_STAT_LOGIN; if (imap_send (stream, info, "LOGIN %s %s", user, passwd) < 0) goto failure; } continue; } } } else if (state == IMAP_STAT_STARTTLS) { if (resp->type == IMAP_RESP_TYPE_TAGGED) { if (STRNULLCMP (resp->status, "OK", 2) == 0) { /* It appears the connection can be encrypted, initiate handshaking and continue over an encrypted connection. */ if (iostream_encrypt (stream, ca_file, ca_path, &errstr) < 0) { ocf_log (LOG_ERR, "%s: iostream_encrypt: %s", __func__, errstr); goto failure; } ocf_log (LOG_DEBUG, "%s: encrypted connection", __func__); state = IMAP_STAT_LOGIN; if (imap_send (stream, info, "LOGIN %s %s", user, passwd) < 0) goto failure; continue; } } } else if (state == IMAP_STAT_LOGIN) { if (resp->type == IMAP_RESP_TYPE_TAGGED) { if (STRNULLCMP (resp->status, "OK", 2) == 0) { ocf_log (LOG_DEBUG, "%s: logged in", __func__); state = IMAP_STAT_SELECT; if (imap_send (stream, info, "SELECT INBOX") < 0) goto failure; continue; } } else if (STRNULLCMP (resp->extra, "CAPABILITY", 10) == 0) { /* server is allowed to send CAPABILITY in response to LOGIN */ continue; } } else if (state == IMAP_STAT_SELECT) { if (resp->type == IMAP_RESP_TYPE_UNTAGGED) { continue; } else if (resp->type == IMAP_RESP_TYPE_TAGGED) { if (STRNULLCMP (resp->status, "OK", 2) == 0) { ocf_log (LOG_DEBUG, "%s: selected INBOX", __func__); state = IMAP_STAT_LOGOUT; if (imap_send (stream, info, "LOGOUT") < 0) goto failure; continue; } } } else if (state == IMAP_STAT_LOGOUT) { /* The expected BYE response is handled above. */ if (resp->type == IMAP_RESP_TYPE_TAGGED) { if (STRNULLCMP (resp->status, "OK", 2) == 0) { ocf_log (LOG_DEBUG, "%s: logged out", __func__); break; } } } else { ocf_log (LOG_ERR, "%s: unknown state, bailing", __func__); state = IMAP_STAT_LOGOUT; if (imap_send (stream, info, "LOGOUT") < 0) goto failure; } /* error condition, extra information might be available */ if (resp->status && resp->extra && (strncmp (resp->status, "NO", 2) == 0 || strncmp (resp->status, "BAD", 3) == 0)) ocf_log (LOG_ERR, "%s: %s", __func__, resp->extra); else ocf_log (LOG_ERR, "%s: unknown error", __func__); goto failure_protocol; } if (0) { failure: result = IMAP_ERR_SYSTEM; } if (0) { failure_protocol: result = IMAP_ERR_PROTOCOL; } iostream_deinit (stream); /* also calls iostream_disconnect */ imap_info_free (info); imap_resp_free (resp); return result; }