/*
in.pop3gwd, a POP3 proxy
Copyright (C) 1997 Andrea Borgia
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* connect_login.c: connect to remote host and log in */
/* ------------------------------------------------------ */
#include "pop3-gw.h"
/*
* open a TCP connection;
* return socket descriptor if OK, else BAD on error
*/
static int contact_host(char hostname[], int port) {
struct sockaddr_in tcp_srv_addr; /* server's Internet socket addr */
struct hostent *host_ptr; /* from gethostbyname() */
int remote_fd; /* on exit, holds descriptor no. or BAD if failed */
if ((host_ptr = gethostbyname(hostname)) == NULL)
remote_fd = BAD;
else
if ((remote_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
remote_fd = BAD;
else {
memset(&tcp_srv_addr, 0, sizeof(tcp_srv_addr));
tcp_srv_addr.sin_family = AF_INET;
tcp_srv_addr.sin_port = htons(port);
memcpy(&tcp_srv_addr.sin_addr, host_ptr->h_addr_list[0], host_ptr->h_length);
if (connect(remote_fd, (struct sockaddr *) &tcp_srv_addr, sizeof(tcp_srv_addr)) <0) {
close(remote_fd);
remote_fd = BAD;
}
}
return(remote_fd);
}
/*
* connect to the remote host and login; return code is TRUE if logged in successfully
* (the remote server's reply has been passed to the proxy user), FALSE if not.
* function takes care to forward the remote server response (positive or negative,
* if any) to the proxy user
*/
int connect_login(int first_filedes, int *remote_filedes, int maxlen, int maxwait,
char username[], char hostname[], int dest_port, const char termin[],
const char pos_re[], const char neg_re[], const char user_c[],
int *conn, int *in, int *out) {
char output[MAX_IO_LEN], input[MAX_IO_LEN];
char to_client[MAX_IO_LEN];
int result = TRUE;
int count;
char *next_tok;
if ((*remote_filedes = contact_host(hostname, dest_port)) == BAD) {
/* no connection, tell user about it */
result = FALSE;
snprintf(to_client, MAX_IO_LEN, "%s host unknown or connection failed", neg_re);
}
if (result == TRUE) {
/* server is connected, wait for reply */
if (readline(*remote_filedes, input, maxlen, maxwait, termin) == BAD) {
/* server did not respond */
close(*remote_filedes);
result = FALSE;
snprintf(to_client, MAX_IO_LEN, "%s no response from server", neg_re);
}
}
if (result == TRUE) {
/* server greeted us, check if greeting is empty */
if ((next_tok = strtok(input, " ")) == NULL) {
/* empty response, POP3 violation */
close(*remote_filedes);
result = FALSE;
snprintf(to_client, MAX_IO_LEN, "%s empty response from server", neg_re);
}
}
if (result == TRUE) {
/* server greeted us, check if +OK */
if (strncasecmp(next_tok, pos_re, maxlen) != 0) {
close(*remote_filedes);
result = FALSE;
snprintf(to_client, MAX_IO_LEN, "%s invalid response from remote server", neg_re);
}
}
if (result == TRUE) {
/* greeting is OK, we may login now */
snprintf(output, MAX_IO_LEN, "%s %s%s", user_c, username, termin);
if (writen(*remote_filedes, output, strlen(output), maxwait) != strlen(output)) {
close(*remote_filedes);
result = FALSE;
snprintf(to_client, MAX_IO_LEN, "%s could not send USER to remote server", neg_re);
}
}
if (result == TRUE) {
/* now let's see if the remote server replies to our USER cmd */
if (readline(*remote_filedes, input, MAX_IO_LEN, maxwait, termin) == BAD) {
close(*remote_filedes);
result = FALSE;
snprintf(to_client, MAX_IO_LEN, "%s no response to USER", neg_re);
}
}
if (result == TRUE) {
/* server replied, check if reply is empty */
/* must save response in case it is good */
(void)strlcpy(to_client, input, MAX_IO_LEN);
if ((next_tok = strtok(input, " ")) == NULL) {
/* empty response, POP3 violation */
close(*remote_filedes);
result = FALSE;
snprintf(to_client, MAX_IO_LEN, "%s empty response from server", neg_re);
}
}
if (result == TRUE) {
/* is reply +OK ? */
if (strncasecmp(next_tok, pos_re, maxlen) != 0) {
/* server did not like out USER... */
close(*remote_filedes);
result = FALSE;
snprintf(to_client, MAX_IO_LEN, "%s login failed", neg_re);
}
}
#ifdef DEBUG
syslog(LOG_PRIO, "%s", to_client);
#endif
(void)strlcat(to_client, termin, MAX_IO_LEN);
if ((count = writen(first_filedes, to_client, strlen(to_client), maxwait)) == strlen(to_client))
*out += count;
else
*conn = FALSE;
return(result);
}
syntax highlighted by Code2HTML, v. 0.9.1