/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
*
* 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
# include <netinet/ip.h>
#endif
-#ifdef HAVE_STDINT_H
-# include <stdint.h> /* e.g. for Mac OS X */
-#endif
-
#ifdef TCPWRAP
# include <tcpd.h> /* for TCP Wrappers */
#endif
#include "client.h"
#include "class.h"
#include "conf.h"
+#include "conn-encoding.h"
#include "conn-ssl.h"
#include "conn-zip.h"
#include "conn-func.h"
static bool Handle_Write PARAMS(( CONN_ID Idx ));
static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
-static int New_Connection PARAMS(( int Sock ));
+static int New_Connection PARAMS(( int Sock, bool IsSSL ));
static CONN_ID Socket2Index PARAMS(( int Sock ));
static void Read_Request PARAMS(( CONN_ID Idx ));
static unsigned int Handle_Buffer PARAMS(( CONN_ID Idx ));
cb_listen(int sock, short irrelevant)
{
(void) irrelevant;
- (void) New_Connection(sock);
+ (void) New_Connection(sock, false);
}
int fd;
(void) irrelevant;
- fd = New_Connection(sock);
+ fd = New_Connection(sock, true);
if (fd < 0)
return;
io_event_setcb(My_Connections[fd].sock, cb_clientserver_ssl);
#endif
{
char buffer[COMMAND_LEN];
+#ifdef ICONV
+ char *ptr, *message;
+#endif
size_t len;
bool ok;
va_list ap;
CUT_TXTSUFFIX);
}
+#ifdef ICONV
+ ptr = strchr(buffer + 1, ':');
+ if (ptr) {
+ ptr++;
+ message = Conn_EncodingTo(Idx, ptr);
+ if (message != ptr)
+ strlcpy(ptr, message, sizeof(buffer) - (ptr - buffer));
+ }
+#endif
+
#ifdef SNIFFER
if (NGIRCd_Sniffer)
Log(LOG_DEBUG, " -> connection %d: '%s'.", Idx, buffer);
return ok;
} /* Conn_WriteStr */
+GLOBAL char*
+Conn_Password( CONN_ID Idx )
+{
+ assert( Idx > NONE );
+ if (My_Connections[Idx].pwd == NULL)
+ return (char*)"\0";
+ else
+ return My_Connections[Idx].pwd;
+} /* Conn_Password */
+
+GLOBAL void
+Conn_SetPassword( CONN_ID Idx, const char *Pwd )
+{
+ assert( Idx > NONE );
+
+ if (My_Connections[Idx].pwd)
+ free(My_Connections[Idx].pwd);
+
+ My_Connections[Idx].pwd = strdup(Pwd);
+ if (My_Connections[Idx].pwd == NULL) {
+ Log(LOG_EMERG, "Can't allocate memory! [Conn_SetPassword]");
+ exit(1);
+ }
+} /* Conn_SetPassword */
/**
* Append Data to the outbound write buffer of a connection.
array_free(&My_Connections[Idx].rbuf);
array_free(&My_Connections[Idx].wbuf);
+ if (My_Connections[Idx].pwd != NULL)
+ free(My_Connections[Idx].pwd);
/* Clean up connection structure (=free it) */
Init_Conn_Struct( Idx );
* Initialize new client connection on a listening socket.
*
* @param Sock Listening socket descriptor.
+ * @param IsSSL true if this socket expects SSL-encrypted data.
* @returns Accepted socket descriptor or -1 on error.
*/
static int
-New_Connection(int Sock)
+New_Connection(int Sock, UNUSED bool IsSSL)
{
#ifdef TCPWRAP
struct request_info req;
#endif
ng_ipaddr_t new_addr;
char ip_str[NG_INET_ADDRSTRLEN];
- int new_sock, new_sock_len, identsock;
+ int new_sock, new_sock_len;
CLIENT *c;
long cnt;
Log(LOG_INFO, "Accepted connection %d from %s:%d on socket %d.",
new_sock, My_Connections[new_sock].host,
ng_ipaddr_getport(&new_addr), Sock);
+ Account_Connection();
+
+#ifdef SSL_SUPPORT
+ /* Delay connection initalization until SSL handshake is finished */
+ if (!IsSSL)
+#endif
+ Conn_StartLogin(new_sock);
+
+ return new_sock;
+} /* New_Connection */
+
+
+/**
+ * Finish connection initialization, start resolver subprocess.
+ *
+ * @param Idx Connection index.
+ */
+GLOBAL void
+Conn_StartLogin(CONN_ID Idx)
+{
+ int ident_sock = -1;
+
+ assert(Idx >= 0);
+
+ /* Nothing to do if DNS (and resolver subprocess) is disabled */
+ if (!Conf_DNS)
+ return;
- identsock = new_sock;
#ifdef IDENTAUTH
- if (!Conf_Ident)
- identsock = -1;
+ /* Should we make an IDENT request? */
+ if (Conf_Ident)
+ ident_sock = My_Connections[Idx].sock;
#endif
- if (Conf_DNS) {
- if (Conf_NoticeAuth) {
+
+ if (Conf_NoticeAuth) {
+ /* Send "NOTICE AUTH" messages to the client */
#ifdef IDENTAUTH
- if (Conf_Ident)
- (void)Conn_WriteStr(new_sock,
- "NOTICE AUTH :*** Looking up your hostname and checking ident");
- else
+ if (Conf_Ident)
+ (void)Conn_WriteStr(Idx,
+ "NOTICE AUTH :*** Looking up your hostname and checking ident");
+ else
#endif
- (void)Conn_WriteStr(new_sock,
- "NOTICE AUTH :*** Looking up your hostname");
- }
- Resolve_Addr(&My_Connections[new_sock].proc_stat, &new_addr,
- identsock, cb_Read_Resolver_Result);
+ (void)Conn_WriteStr(Idx,
+ "NOTICE AUTH :*** Looking up your hostname");
+ (void)Handle_Write(Idx);
}
- Account_Connection();
- return new_sock;
-} /* New_Connection */
+ Resolve_Addr(&My_Connections[Idx].proc_stat, &My_Connections[Idx].addr,
+ ident_sock, cb_Read_Resolver_Result);
+}
/**
if (!array_catb(&My_Connections[Idx].zip.rbuf, readbuf,
(size_t) len)) {
Log(LOG_ERR,
- "Could not append recieved data to zip input buffer (connection %d): %d bytes!",
+ "Could not append received data to zip input buffer (connection %d): %d bytes!",
Idx, len);
Conn_Close(Idx, "Receive buffer space exhausted", NULL,
false);
{
if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
Log(LOG_ERR,
- "Could not append recieved data to input buffer (connection %d): %d bytes!",
+ "Could not append received data to input buffer (connection %d): %d bytes!",
Idx, len);
Conn_Close(Idx, "Receive buffer space exhausted", NULL, false );
}
if (My_Connections[i].lastping <
time(NULL) - Conf_PongTimeout) {
/* Timeout */
- LogDebug
- ("Connection %d: Ping timeout: %d seconds.",
- i, Conf_PongTimeout);
- snprintf(msg, sizeof(msg), "Ping timeout: %d seconds", Conf_PongTimeout);
+ snprintf(msg, sizeof(msg),
+ "Ping timeout: %d seconds",
+ Conf_PongTimeout);
+ LogDebug("Connection %d: %s.", i, msg);
Conn_Close(i, NULL, msg, true);
}
} else if (My_Connections[i].lastdata <
assert( Server > NONE );
+ /* Make sure that the remote server hasn't re-linked to this server
+ * asynchronously on its own */
+ if (Conf_Server[Server].conn_id > NONE) {
+ Log(LOG_INFO,
+ "Connection to \"%s\" meanwhile re-established, aborting preparation.");
+ return;
+ }
+
if (!ng_ipaddr_tostr_r(dest, ip_str)) {
Log(LOG_WARNING, "New_Server: Could not convert IP to string");
return;
Client_SetToken( c, TOKEN_OUTBOUND );
/* Register connection */
- Conf_Server[Server].conn_id = new_sock;
+ if (!Conf_SetServer(Server, new_sock))
+ return;
My_Connections[new_sock].sock = new_sock;
My_Connections[new_sock].addr = *dest;
My_Connections[new_sock].client = c;
My_Connections[Idx].lastdata = now;
My_Connections[Idx].lastprivmsg = now;
Proc_InitStruct(&My_Connections[Idx].proc_stat);
+
+#ifdef ICONV
+ My_Connections[Idx].iconv_from = (iconv_t)(-1);
+ My_Connections[Idx].iconv_to = (iconv_t)(-1);
+#endif
} /* Init_Conn_Struct */
char *identptr;
#ifdef IDENTAUTH
char readbuf[HOST_LEN + 2 + CLIENT_USER_LEN];
+ char *ptr;
#else
char readbuf[HOST_LEN + 1];
#endif
Client_SetHostname(c, readbuf);
if (Conf_NoticeAuth)
(void)Conn_WriteStr(i,
- "NOTICE AUTH :*** Found your hostname");
+ "NOTICE AUTH :*** Found your hostname: %s",
+ My_Connections[i].host);
#ifdef IDENTAUTH
++identptr;
if (*identptr) {
- Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
- Client_SetUser(c, identptr, true);
- if (Conf_NoticeAuth)
+ ptr = identptr;
+ while (*ptr) {
+ if ((*ptr < '0' || *ptr > '9') &&
+ (*ptr < 'A' || *ptr > 'Z') &&
+ (*ptr < 'a' || *ptr > 'z'))
+ break;
+ ptr++;
+ }
+ if (*ptr) {
+ /* Erroneous IDENT reply */
+ Log(LOG_NOTICE,
+ "Got invalid IDENT reply for connection %d! Ignored.",
+ i);
+ } else {
+ Log(LOG_INFO,
+ "IDENT lookup for connection %d: \"%s\".",
+ i, identptr);
+ Client_SetUser(c, identptr, true);
+ }
+ if (Conf_NoticeAuth) {
(void)Conn_WriteStr(i,
- "NOTICE AUTH :*** Got ident response");
+ "NOTICE AUTH :*** Got %sident response%s%s",
+ *ptr ? "invalid " : "",
+ *ptr ? "" : ": ",
+ *ptr ? "" : identptr);
+ }
} else {
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
if (Conf_NoticeAuth && Conf_Ident)
"NOTICE AUTH :*** No ident response");
}
#endif
+
+ if (Conf_NoticeAuth)
+ (void)Handle_Write(i);
+
Class_HandleServerBans(c);
}
#ifdef DEBUG