[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tpop3d-discuss] signal 11?
From: |
Nancy Pettigrew (work) |
Subject: |
[tpop3d-discuss] signal 11? |
Date: |
Tue, 17 Jul 2001 16:43:18 -0700 |
Why would the process get the SIGSEGV after returning an error back from the
auth_mysql_new_user_pass function?
I've seen it happen in a few different instances, this is the only log
instance where some other error was reported prior to the signal 11:
Jul 17 21:49:36 mail1 tpop3d[30213]: auth_mysql_new_user_pass:
mysql_store_result: Lost connection to MySQL server during query
Jul 17 21:49:36 mail1 tpop3d[30213]: quit: signal 11
In other instances of the signal 11 logging, the auth_mysql_new_user_pass
function didn't log any errors. The server then hung up for a few minutes,
not properly accepting connections, and then began accepting connections
again.
I tweaked the auth_mysql_new_user_pass function to do an additional query
for my setup, and I'm wondering if there's something I've missed that a
subsequent process needs...basically, I've changed it to use different
tables, and to do an additional query to translate domains for a domain
aliasing situation on the system. I've gone through it several times,
perhaps I'm having a proofreading mental block, I don't know. Any input
would be greatly appreciated.
Thanks,
Nancy
I'm using version 1.3.3.
Here's my tweaked version of auth_mysql_new_user_pass:
/* auth_mysql_new_user_pass:
*/
char user_pass_query_template[] =
"SELECT distinct '/var/spool/mail', m.mail_location, m.user_password,
'mail' "
"FROM users m LEFT JOIN aliases AS a ON m.user_id = a.user_id "
"WHERE (a.address='address@hidden' OR m.primary_email = 'address@hidden')
AND DateDeleted
IS NULL";
char domain_trans_query_template[] =
"SELECT new_domain "
"FROM domain_translate "
"WHERE domain = '%s'";
authcontext auth_mysql_new_user_pass(const char *user, const char *pass) {
char *query, *x, *y, *dt_query;
authcontext a = NULL;
char *local_part;
char *domain;
char *p;
unsigned char *q;
item *I;
size_t l, dt_l;
int use_gid = 0;
gid_t gid;
if (!mysql) return NULL;
/* Obtain gid to use */
if ((I = stringmap_find(config, "auth-mysql-mail-group"))) {
if (!parse_gid((char*)I->v, &gid)) {
print_log(LOG_ERR, _("auth_mysql_new_user_pass:
auth-mysql-mail-group directive `%s' does not make sense"), (char*)I->v);
return NULL;
}
use_gid = 1;
}
domain = user + strcspn(user, "@%!");
if (domain == user || !*domain) return NULL;
++domain;
local_part = (char*)malloc(domain - user);
if (!local_part) return NULL;
memset(local_part, 0, domain - user);
strncpy(local_part, user, domain - user - 1);
if (mysql_ping(mysql) == -1) {
print_log(LOG_ERR, "auth_mysql_new_user_pass: mysql_ping: %s",
mysql_error(mysql));
return NULL;
}
/* get domain_translate, if applicable */
dt_query = (char*)malloc(dt_l = (sizeof(domain_trans_query_template) +
strlen(domain) + 1));
if (!dt_query) goto fail;
snprintf(dt_query, dt_l, domain_trans_query_template, domain);
if (mysql_query(mysql, dt_query) == 0) {
MYSQL_RES *dt_result = mysql_store_result(mysql);
int j;
if (!dt_result) {
print_log(LOG_ERR, "auth_mysql_new_user_pass:
mysql_store_result: %s", mysql_error(mysql));
goto fail;
}
switch (j = mysql_num_rows(dt_result)) {
case 0:
break;
case 1: {
MYSQL_ROW dt_row = mysql_fetch_row(dt_result);
domain = (char*)dt_row[0];
break;
}
default:
print_log(LOG_ERR, _("auth_mysql_new_user_pass: database
inconsistency: query returned %d rows"), j);
break;
}
mysql_free_result(dt_result);
} else {
print_log(LOG_ERR, "auth_mysql_new_user_pass: mysql_query: %s",
mysql_error(mysql));
goto fail;
}
query = (char*)malloc(l = (sizeof(user_pass_query_template) +
(strlen(local_part) * 4) + (strlen(domain) * 4)));
x = (char*)malloc(strlen(local_part) * 2 + 1);
y = (char*)malloc(strlen(domain) * 2 + 1);
if (!query || !x || !y) goto fail;
mysql_escape_string(x, local_part, strlen(local_part));
mysql_escape_string(y, domain, strlen(domain));
snprintf(query, l, user_pass_query_template, x, y, x, y);
if (mysql_query(mysql, query) == 0) {
MYSQL_RES *result = mysql_store_result(mysql);
int i;
if (!result) {
print_log(LOG_ERR, "auth_mysql_new_user_pass:
mysql_store_result: %s", mysql_error(mysql));
goto fail;
}
switch (i = mysql_num_rows(result)) {
case 0:
break;
case 1: {
MYSQL_ROW row = mysql_fetch_row(result);
unsigned long *lengths;
char *pwhash;
char *mailbox;
struct passwd *pw;
int authok = 0;
uid_t uid;
/* These are "can't happen" errors */
if (!row || !(lengths = mysql_fetch_lengths(result))) break;
/* Verify the password. There are several possibilities
here. */
pwhash = (char*)row[2];
if (strncmp(pwhash, "{crypt}", 7) == 0) {
/* Password hashed by system crypt function. */
if (strcmp(crypt(pass, pwhash + 7), pwhash + 7) == 0)
authok = 1;
} else if (strncmp(pwhash, "{crypt_md5}", 11) == 0) {
/* Password hashed by crypt_md5. */
if (strcmp(crypt_md5(pass, pwhash + 11), pwhash + 11) ==
0) authok = 1;
} else if (strncmp(pwhash, "{plaintext}", 11) == 0) {
/* Plain text password, as used for APOP. */
if (strcmp(pass, pwhash + 11) == 0) authok = 1;
} else if (strncmp(pwhash, "{md5}", 4) == 0 || *pwhash !=
'{') {
/* Straight MD5 password. */
MD5_CTX ctx;
unsigned char digest[16];
char hexhash[33] = {0};
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char*)pass, strlen(pass));
MD5Final(digest, &ctx);
for (p = hexhash, q = digest; q < digest + 16; ++q, p +=
2) snprintf(p, 3, "%02x", (unsigned)*q);
if (strcasecmp(hexhash, pwhash + 5) == 0 ||
strcasecmp(hexhash, pwhash) == 0) authok = 1;
} else {
/* Unknown format. */
print_log(LOG_ERR, _("auth_mysql_new_user_pass:
address@hidden
has unknown password format `%.*s'"), local_part, domain, 2 + strcspn(pwhash
+ 1, "}"), pwhash);
break;
}
if (!authok) {
print_log(LOG_ERR, _("auth_mysql_new_user_pass:
address@hidden
failed login with wrong password"), local_part, domain);
break;
}
if (!parse_uid((const char*)row[3], &uid)) {
print_log(LOG_ERR, _("auth_mysql_new_user_pass: unix
user `%s' for address@hidden does not make sense"), row[3], local_part, domain);
break;
}
pw = getpwuid(uid);
if (!pw) {
print_log(LOG_ERR, "auth_mysql_new_user_pass:
getpwuid(%d): %m", (int)uid);
break;
}
mailbox = (char*)malloc(l = (lengths[0] + lengths[1] + 2));
snprintf(mailbox, l, "%s%s", row[0], row[1]);
a = authcontext_new(pw->pw_uid, use_gid ? gid : pw->pw_gid,
NULL, mailbox, NULL, domain); /* note
default mailbox type. */
free(mailbox);
break;
}
default:
print_log(LOG_ERR, _("auth_mysql_new_user_pass: database
inconsistency: query for address@hidden returned %d rows"), local_part, domain,
i);
break;
}
mysql_free_result(result);
} else {
print_log(LOG_ERR, "auth_mysql_new_user_pass: mysql_query: %s",
mysql_error(mysql));
}
fail:
if (local_part) free(local_part);
if (x) free(x);
if (y) free(y);
if (query) free(query);
if (dt_query) free(dt_query);
return a;
}