/** * A simple 'SSH protocol version exchange' implemetation based on RFC (http://www.openssh.com/txt/draft-ietf-secsh-transport-14.txt) * * @file */ void check_ssh(Socket_T socket) { char buf[STRLEN]; ASSERT(socket); if (! Socket_readLine(socket, buf, sizeof(buf))) THROW(IOException, "SSH: error receiving identification string -- %s", STRERROR); if (! Str_startsWith(buf, "SSH-")) THROW(IOException, "SSH: protocol error %s", buf); /* send identification string back to server */ if (Socket_write(socket, buf, strlen(buf)) <= 0) THROW(IOException, "SSH: error sending identification string -- %s", STRERROR); /* Read one extra line to prevent the "Read from socket failed" warning */ Socket_readLine(socket, buf, sizeof(buf)); }
/** * Check the server for greeting code 220 and then send a QUIT and check for code 221 * * @file */ void check_ftp(Socket_T socket) { int status; char buf[STRLEN]; ASSERT(socket); do { if (! Socket_readLine(socket, buf, STRLEN)) THROW(IOException, "FTP: error receiving data -- %s", STRERROR); Str_chomp(buf); } while (buf[3] == '-'); // Discard multi-line response if (sscanf(buf, "%d", &status) != 1 || status != 220) THROW(IOException, "FTP greeting error: %s", buf); if (Socket_print(socket, "QUIT\r\n") < 0) THROW(IOException, "FTP: error sending data -- %s", STRERROR); if (! Socket_readLine(socket, buf, STRLEN)) THROW(IOException, "FTP: error receiving data -- %s", STRERROR); Str_chomp(buf); if (sscanf(buf, "%d", &status) != 1 || status != 221) THROW(IOException, "FTP quit error: %s", buf); }
static void do_status(SendMail_T *S) { int status = 0; StringBuffer_clear(S->status_message); char buf[STRLEN]; do { if (! Socket_readLine(S->socket, buf, sizeof(buf))) THROW(IOException, "Error receiving data from the mailserver '%s' -- %s", S->server, STRERROR); StringBuffer_append(S->status_message, "%s", buf); } while (buf[3] == '-'); // multi-line response Str_chomp(buf); if (sscanf(buf, "%d", &status) != 1 || status < 200 || status >= 400) THROW(IOException, "%s", buf); }
static void _receive(T S, int code, void (*callback)(T S, const char *line)) { int status = 0; char line[STRLEN]; do { if (! Socket_readLine(S->socket, line, sizeof(line))) THROW(IOException, "Error receiving data from the mailserver -- %s", STRERROR); Str_chomp(line); if (strlen(line) < 4 || sscanf(line, "%d", &status) != 1 || status != code) THROW(IOException, "Mailserver response error -- %s", line); if (callback) callback(S, line); } while (line[3] == '-'); // multi-line response }
/** * Check the server for greeting code +OK, then send QUIT and check for code +OK * * @file */ void check_pop(Socket_T socket) { ASSERT(socket); char buf[STRLEN]; const char *ok = "+OK"; // Read and check POP greeting if (! Socket_readLine(socket, buf, sizeof(buf))) THROW(IOException, "POP: greeting read error -- %s", errno ? STRERROR : "no data"); Str_chomp(buf); if (strncasecmp(buf, ok, strlen(ok)) != 0) THROW(IOException, "POP: invalid greeting -- %s", buf); // QUIT and check response if (Socket_print(socket, "QUIT\r\n") < 0) THROW(IOException, "POP: QUIT command error -- %s", STRERROR); if (! Socket_readLine(socket, buf, sizeof(buf))) THROW(IOException, "POP: QUIT response read error -- %s", errno ? STRERROR : "no data"); Str_chomp(buf); if (strncasecmp(buf, ok, strlen(ok)) != 0) THROW(IOException, "POP: invalid QUIT response -- %s", buf); }
/** * Simple redis RESP protocol ping test: * * 1. send a PING command * 2. expect a PONG response * 3. send a QUIT command * * @see http://redis.io/topics/protocol * * @file */ void check_redis(Socket_T socket) { ASSERT(socket); char buf[STRLEN]; if (Socket_print(socket, "*1\r\n$4\r\nPING\r\n") < 0) THROW(IOException, "REDIS: PING command error -- %s", STRERROR); if (! Socket_readLine(socket, buf, sizeof(buf))) THROW(IOException, "REDIS: PING response error -- %s", STRERROR); Str_chomp(buf); if (! Str_isEqual(buf, "+PONG") && ! Str_startsWith(buf, "-NOAUTH")) // We accept authentication error (-NOAUTH Authentication required): redis responded to request, but requires authentication => we assume it works THROW(IOException, "REDIS: PING error -- %s", buf); if (Socket_print(socket, "*1\r\n$4\r\nQUIT\r\n") < 0) THROW(IOException, "REDIS: QUIT command error -- %s", STRERROR); }
/** * Check the server for greeting "@RSYNCD: XX, then send this greeting back to server, send command '#list' to get a listing of modules. * * @file */ void check_rsync(Socket_T socket) { char buf[64]; char header[11]; int rc, version_major, version_minor; char *rsyncd = "@RSYNCD:"; char *rsyncd_exit = "@RSYNCD: EXIT"; ASSERT(socket); /* Read and check the greeting */ if (! Socket_readLine(socket, buf, sizeof(buf))) THROW(IOException, "RSYNC: did not see server greeting -- %s", STRERROR); Str_chomp(buf); rc = sscanf(buf, "%10s %d.%d", header, &version_major, &version_minor); if ((rc == EOF) || (rc != 3)) THROW(IOException, "RSYNC: server greeting parse error %s", buf); if (strncasecmp(header, rsyncd, strlen(rsyncd)) != 0) THROW(IOException, "RSYNC: server sent unexpected greeting -- %s", buf); /* Send back the greeting */ if (Socket_print(socket, "%s\n", buf) <= 0) THROW(IOException, "RSYNC: identification string send failed -- %s", STRERROR); /* Send #list command */ if (Socket_print(socket, "#list\n") < 0) THROW(IOException, "RSYNC: #list command failed -- %s", STRERROR); /* Read response: discard list output and check that we've received successful exit */ do { if (! Socket_readLine(socket, buf, sizeof(buf))) THROW(IOException, "RSYNC: error receiving data -- %s", STRERROR); Str_chomp(buf); } while (strncasecmp(buf, rsyncd, strlen(rsyncd))); if (strncasecmp(buf, rsyncd_exit, strlen(rsyncd_exit)) != 0) THROW(IOException, "RSYNC: server sent unexpected response -- %s", buf); }
void check_sip(Socket_T socket) { ASSERT(socket); Port_T P = Socket_getPort(socket); ASSERT(P); const char *target = P->parameters.sip.target ? P->parameters.sip.target : "*****@*****.**"; int port = Socket_getLocalPort(socket); char *proto = Socket_isSecure(socket) ? "sips" : "sip"; char *transport = ""; char *rport = ""; switch (Socket_getType(socket)) { case Socket_Udp: transport = "UDP"; rport = ";rport"; break; case Socket_Tcp: transport = "TCP"; break; default: THROW(IOException, "Unsupported socket type, only TCP and UDP are supported"); break; } char buf[STRLEN]; const char *myip = Socket_getLocalHost(socket, buf, sizeof(buf)); if (Socket_print(socket, "OPTIONS %s:%s SIP/2.0\r\n" "Via: SIP/2.0/%s %s:%d;branch=z9hG4bKh%ld%s\r\n" "Max-Forwards: %d\r\n" "To: <%s:%s>\r\n" "From: monit <%s:monit@%s>;tag=%ld\r\n" "Call-ID: %ld\r\n" "CSeq: 63104 OPTIONS\r\n" "Contact: <%s:%s:%d>\r\n" "Accept: application/sdp\r\n" "Content-Length: 0\r\n" "User-Agent: Monit/%s\r\n\r\n", proto, // protocol target, // to transport, // via transport udp|tcp myip, // who its from port, // our port random(), // branch rport, // rport option P->parameters.sip.maxforward ? P->parameters.sip.maxforward : 70, // maximum forwards proto, // protocol target, // to proto, // protocol myip, // from host random(), // tag random(), // call id proto, // protocol myip, // contact host port, // contact port VERSION // user agent ) < 0) { THROW(IOException, "SIP: error sending data -- %s", STRERROR); } if (! Socket_readLine(socket, buf, sizeof(buf))) THROW(IOException, "SIP: error receiving data -- %s", STRERROR); Str_chomp(buf); DEBUG("Response from SIP server: %s\n", buf); int status; if (! sscanf(buf, "%*s %d", &status)) THROW(IOException, "SIP error: cannot parse SIP status in response: %s", buf); if (status >= 400) THROW(IOException, "SIP error: Server returned status %d", status); if (status >= 300 && status < 400) THROW(IOException, "SIP info: Server redirection. Returned status %d", status); if (status > 100 && status < 200) THROW(IOException, "SIP error: Provisional response . Returned status %d", status); }