Svetozar Mihailov pisze:
Hello Pawel,

Hi Svetozar,

Thanks for answer. Anyway things was changed a little. Now I have
cluster from 6 hardware nodes ( Q6600, 8G ram, CentOS 5.2 ) using iscsi
gfs2 shared storage plus quorum disk also on iscsi. So I can shutdown 5
nodes, and cluster will be quorate with single node.

Very interesting setup. I like it. Can I feel free to grab some your ideas? ;)

I of course prefer Linux. In fact I do not use anything else. And
windows dns cache is not problem, because windows machines do not work
long enough without reboot.

Sometime I thought the same. Now I know that some of my users never
shut down their Windows boxes and they still work ;)

After this I will try to make few changes to courier. Most important for
me is to modify auth protocol to include sender IP address. With this
change my already modified mysql backend will log spammers ip directly
to mysql and after few weeks my local rbl dns will be good as public
ones. Same logging I must do for spam/virus filters.

We also need to have that feature and patched our Courier. Look at attached diffs. You can use or modify it, if you want. Feel free to
ask me if something is not understandable for you.

These patches do round-robin logging of all our Courier services (SMTP/POP3/IMAP/webmail) into the following MySQL tables:

mysql> desc user_login_rr;
+------------+---------------------------+------+-----+---------+-------+
| Field      | Type                      | Null | Key | Default | Extra |
+------------+---------------------------+------+-----+---------+-------+
| user_id    | int(11) unsigned          | NO   | PRI | 0       |       |
| service_id | enum('E','P','I','W','A') | NO   | PRI | E       |       |
| login_id   | int(5) unsigned           | NO   |     | 0       |       |
+------------+---------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>

`user_id` column is for numerical user identity in `users` table.
It contains all user's details (name, fullname, home, maildir, status, etc), except for his login part(s), it means main login part or/and alias(es). We store the local parts in different table named `user_local_part`:

mysql> desc user_local_part;
+---------------+-------------------+------+-----+---------+-------+
| Field         | Type              | Null | Key | Default | Extra |
+---------------+-------------------+------+-----+---------+-------+
| user_id       | int(11) unsigned  | YES  |     | 0       |       |
| local_part    | varchar(128)      | NO   | MUL |         |       |
| local_part_id | enum('G','A','P') | NO   |     | G       |       |
| forward       | varchar(128)      | YES  |     | NULL    |       |
+---------------+-------------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql>

'E' for `service_id` field stands for ESMTP service, 'P' - POP3,
'I' - IMAP, 'W' - webmail. 'A' is for administration web interface
for our Helpdesk. Please note, that we don't differentiate "normal"
and secured services via SSL, for example POP3 and POP3S.

mysql> desc user_login;
+------------+---------------------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------------------+------+-----+-------------------+-------+
| user_id | int(11) unsigned | NO | MUL | 0 | | | service_id | enum('E','P','I','W','A') | YES | | NULL | | | login_id | int(5) unsigned | NO | | 0 | | | login_ts | timestamp | NO | | CURRENT_TIMESTAMP | | | success | enum('Y','N') | NO | | N | | | ip | varchar(23) | YES | | NULL | |
+------------+---------------------------+------+-----+-------------------+-------+
6 rows in set (0.00 sec)

mysql>

Note: the patches are against older version of Courier, so probably you need to fix it to apply against the newest version. I've noticed that
it's a problem with IP logging occasionally. Then I can see "(null)"
in [EMAIL PROTECTED] column instead of client's IP address.

Have I nice Courier patching,

Pawel


Index: courier-0.53.2/imap/imaplogin.c
===================================================================
RCS file: /home/cvs/uwmail/sources/courier/courier-0.53.2/imap/imaplogin.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- courier-0.53.2/imap/imaplogin.c	6 Jun 2006 08:38:06 -0000	1.1
+++ courier-0.53.2/imap/imaplogin.c	8 Jun 2006 10:45:45 -0000	1.2
@@ -372,9 +372,21 @@
 		if (!p || !*p)
 			p="imap";
 
-		rc=auth_login(p, userid, passwd, login_callback, (void *)tag);
+		/* Passing IP */
+		char *buf=malloc(strlen(userid)+strlen(getenv("TCPREMOTEIP"))+2);
+		if (!buf)
+		{
+			perror("ERR: out of memory");
+			writes("* BYE Temporary problem, please try again later\r\n");
+			writeflush();
+			exit(1);
+		}
+		strcat(strcat(strcpy(buf,userid),":"),getenv("TCPREMOTEIP"));
+		
+		rc=auth_login(p, buf, passwd, login_callback, (void *)tag);
 		courier_safe_printf("INFO: LOGIN FAILED, user=%s, ip=[%s]",
 				  userid, getenv("TCPREMOTEIP"));
+		free(buf);
 		free(userid);
 		free(passwd);
 		if (rc > 0)
Index: courier-0.53.2/imap/pop3login.c
===================================================================
RCS file: /home/cvs/uwmail/sources/courier/courier-0.53.2/imap/pop3login.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- courier-0.53.2/imap/pop3login.c	6 Jun 2006 08:38:06 -0000	1.1
+++ courier-0.53.2/imap/pop3login.c	8 Jun 2006 10:45:45 -0000	1.2
@@ -418,10 +418,22 @@
 				if (!q || !*q)
 					q="pop3";
 
-				rc=auth_login(q, user, p, login_callback, NULL);
+				/* Passing IP */
+				char *buf=malloc(strlen(user)+strlen(getenv("TCPREMOTEIP"))+2);
+				if (!buf)
+				{
+					perror("ERR: out of memory");
+					printf("-ERR Temporary problem, please try again later\r\n");
+					fflush(stdout);
+					exit(1);
+				}
+
+				strcat(strcat(strcpy(buf,user),":"),getenv("TCPREMOTEIP"));
+				rc=auth_login(q, buf, p, login_callback, NULL);
 				courier_safe_printf("INFO: LOGIN "
 					"FAILED, user=%s, ip=[%s]",
 					user, ip);
+				free(buf);
 				if (rc > 0)
 				{
 					perror("ERR: authentication error");
Index: courier-0.53.2/webmail/auth.c
===================================================================
RCS file: /home/cvs/uwmail/sources/courier/courier-0.53.2/webmail/auth.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- courier-0.53.2/webmail/auth.c	6 Jun 2006 08:38:07 -0000	1.1
+++ courier-0.53.2/webmail/auth.c	8 Jun 2006 10:46:02 -0000	1.2
@@ -156,15 +156,22 @@
 
 const char *do_login(const char *u, const char *p, const char *ip)
 {
-	if (auth_login("webmail", u, p, doauthlogin, (void *)u))
+	/* Passing IP */
+	char *buf=malloc(strlen(u)+strlen(ip)+2);
+	if (!buf) 
+		enomem();
+	strcat(strcat(strcpy(buf,u),":"),ip);
+	if (auth_login("webmail", buf, p, doauthlogin, (void *)u))
 	{
 		courier_safe_printf("INFO: LOGIN FAILED, user=%s, ip=[%s]",
 				  u?u:"", ip);
+		free(buf);
 		return NULL;
 	}
 
 	fprintf(stderr, "INFO: LOGIN, user=%s, ip=[%s]\n", u, ip);
-	return u;
+	free(buf);
+	return u;	
 }
 
 int nochangepass()
Index: courier-authlib-0.58/authmysql.c
===================================================================
RCS file: /home/cvs/uwmail/sources/courier-authlib/courier-authlib-0.58/authmysql.c,v
retrieving revision 1.1
retrieving revision 1.3
diff -u -r1.1 -r1.3
--- courier-authlib-0.58/authmysql.c	19 May 2006 10:38:21 -0000	1.1
+++ courier-authlib-0.58/authmysql.c	24 May 2006 12:38:15 -0000	1.3
@@ -46,6 +46,16 @@
 		return (-1);
 	}
 
+	/* Getting IP */
+	char *ip=0, *p=0;
+ 	if ((p=strrchr(user, ':')))
+	{
+		if (*(p+1))
+			ip=p+1;
+		if ((p=strchr(user,':')))
+			*p=0;
+ 	}
+	
 	authinfo=auth_mysql_getuserinfo(user, service);
 
 	if (!authinfo)		/* Fatal error - such as MySQL being down */
@@ -58,6 +68,7 @@
 	{
 		if (authcheckpassword(pass,authinfo->cryptpw))
 		{
+			auth_mysql_logauth(user, service, ip, 0);
 			errno=EPERM;
 			return (-1);	/* User/Password not found. */
 		}
@@ -66,6 +77,7 @@
 	{
 		if (strcmp(pass, authinfo->clearpw))
 		{
+			auth_mysql_logauth(user, service, ip, 0);
 			if (courier_authdebug_login_level >= 2)
 				DPRINTF("supplied password '%s' does not match clearpasswd '%s'",
 					pass, authinfo->clearpw);
@@ -77,11 +89,13 @@
 	}
 	else
 	{
+		auth_mysql_logauth(user, service, ip, 0);
 		DPRINTF("no password available to compare");
 		errno=EPERM;
 		return (-1);		/* Username not found */
 	}
 
+	auth_mysql_logauth(user, service, ip, 1);
 	memset(&aa, 0, sizeof(aa));
 
 	aa.sysuserid= &authinfo->uid;
Index: courier-authlib-0.58/authmysql.h
===================================================================
RCS file: /home/cvs/uwmail/sources/courier-authlib/courier-authlib-0.58/authmysql.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- courier-authlib-0.58/authmysql.h	19 May 2006 10:38:21 -0000	1.1
+++ courier-authlib-0.58/authmysql.h	22 May 2006 13:48:26 -0000	1.2
@@ -32,4 +32,7 @@
 extern int auth_mysql_pre(const char *, const char *,
                 int (*)(struct authinfo *, void *), void *arg);
 
+extern int auth_mysql_logauth(const char *, const char *, 
+			const char *, int);
+
 #endif

--- courier-authlib-0.58/authmysqllib.c	2007-03-09 13:31:47.000000000 +0100
+++ courier-authlib-0.58/authmysqllib.c	2007-03-09 13:39:50.000000000 +0100
@@ -1167,3 +1167,143 @@
 
 	if (result) mysql_free_result(result);
 }
+
+int auth_mysql_logauth(const char* username, const char* service,
+		       const char* ip, int success)
+{
+const char *username_table	=NULL,
+	   *login_table		=NULL,
+	   *loginrr_table	=NULL,
+	   *userid_field	=NULL,
+	   *username_field	=NULL,
+	   *serviceid_field	=NULL,
+	   *loginid_field	=NULL,
+	   *logints_field	=NULL,
+	   *success_field	=NULL,
+	   *ip_field		=NULL;
+MYSQL_ROW row; 
+MYSQL_RES *result;
+const char *p;
+char query[1000], *username_tmp;
+unsigned int userid, loginid, logincount;
+char serviceid, *q;
+
+	username_table=read_env("MYSQL_LOGAUTH_USERNAME_TABLE");
+	if (!username_table) username_table="user_local_part";
+
+	login_table=read_env("MYSQL_LOGAUTH_LOGIN_TABLE");
+	if (!login_table) login_table="user_login";
+
+	loginrr_table=read_env("MYSQL_LOGAUTH_LOGINRR_TABLE");
+	if (!loginrr_table) loginrr_table="user_login_rr";
+
+	userid_field=read_env("MYSQL_LOGAUTH_USERID_FIELD");
+	if (!userid_field) userid_field="user_id";
+
+	username_field=read_env("MYSQL_LOGAUTH_USERNAME_FIELD");
+	if (!username_field) username_field="local_part";
+
+	serviceid_field=read_env("MYSQL_LOGAUTH_SERVICEID_FIELD");
+	if (!serviceid_field) serviceid_field="service_id";
+
+	loginid_field=read_env("MYSQL_LOGAUTH_LOGINID_FIELD");
+	if (!loginid_field) loginid_field="login_id";
+
+	logints_field=read_env("MYSQL_LOGAUTH_LOGINTS_FIELD");
+	if (!logints_field) logints_field="login_ts";
+
+	success_field=read_env("MYSQL_LOGAUTH_SUCCESS_FIELD");
+	if (!success_field) success_field="success";
+
+	ip_field=read_env("MYSQL_LOGAUTH_IP_FIELD");
+	if (!ip_field) ip_field="ip";
+
+	if ((p=read_env("MYSQL_LOGAUTH_LOGIN_COUNT")) != 0)
+		logincount=(unsigned int) atoi(p);
+	else
+		logincount=10;
+
+	username_tmp=strdup(username);
+	if (q=strchr(username_tmp, '@')) *q=0;
+	
+	sprintf(query, "SELECT %s FROM %s WHERE %s='%s'", userid_field,
+		username_table, username_field, username_tmp);
+	DPRINTF("SQL query: %s\n", query);
+	
+	free(username_tmp);
+	
+	if (mysql_query(mysql, query) ||
+	    !(result = mysql_store_result(mysql)) ||
+	    !mysql_num_rows(result)) return -1;
+
+	row=mysql_fetch_row(result);
+	userid=0;
+	if ((p=row[0]) != 0) userid=(unsigned int) atol(p);
+	mysql_free_result(result);
+
+	serviceid='W';
+	if (!strcmp(service, "esmtp"))		serviceid='E';
+	else if (!strcmp(service, "pop3"))	serviceid='P';
+	else if (!strcmp(service, "imap"))	serviceid='I';
+
+	sprintf(query, "SELECT %s FROM %s WHERE %s=%d AND %s='%c'",
+		loginid_field, loginrr_table, userid_field, userid,
+		serviceid_field, serviceid);
+	DPRINTF("SQL query: %s\n", query);
+
+	if (mysql_query(mysql, query) ||
+	    !(result=mysql_store_result(mysql))) return -1;
+	row=mysql_fetch_row(result);
+	loginid=1;
+	if (mysql_num_rows(result))
+	{
+		if ((p=row[0]) != 0) loginid=(unsigned int) atoi(p);
+		mysql_free_result(result);
+	}
+	else
+	{
+		sprintf(query, "INSERT INTO %s VALUES (%d, '%c', %d)",
+			loginrr_table, userid, serviceid, loginid);
+		DPRINTF("SQL query: %s\n", query);
+		if (mysql_query(mysql, query)) return -1;
+	}
+
+	sprintf(query, "SELECT %s FROM %s WHERE %s=%d AND %s=%d AND %s='%c'",
+		loginid_field, login_table, userid_field, userid,
+		loginid_field, loginid, serviceid_field, serviceid);
+	DPRINTF("SQL query: %s\n", query);
+
+	if (mysql_query(mysql, query) ||
+	    !(result = mysql_store_result(mysql))) return -1;
+	row=mysql_fetch_row(result);
+	if (mysql_num_rows(result))
+	{
+		sprintf(query, "UPDATE %s SET %s=NOW(), %s='%c', %s='%s' "
+			"WHERE %s=%d AND %s=%d AND %s='%c'",
+			login_table, logints_field, success_field,
+			success ? 'Y' : 'N', ip_field, ip,
+			userid_field, userid, loginid_field, loginid,
+			serviceid_field, serviceid);
+		mysql_free_result(result);
+	}
+	else
+	{
+		sprintf(query, "INSERT INTO %s VALUES (%d, '%c', %d, NOW(),"
+			" '%c', '%s')",
+			login_table, userid, serviceid, loginid,
+			success ? 'Y' : 'N', ip);
+	}
+	DPRINTF("SQL query: %s\n", query);
+	
+	if (mysql_query(mysql, query)) return -1;
+	loginid=(loginid % logincount) + 1;
+	sprintf(query, "UPDATE %s SET %s=%d WHERE %s=%d AND %s='%c'",
+		loginrr_table, loginid_field, loginid,
+		userid_field, userid, serviceid_field, serviceid);
+		DPRINTF("SQL query: %s\n", query);
+
+	if (mysql_query(mysql, query)) return -1;
+
+	return 0;
+}
+ 
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
courier-users mailing list
[email protected]
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/courier-users

Reply via email to