Beispiel #1
0
int do_dangling_aliases(void)
{
	int count = 0;
	int result = 0;
	GList *aliases = NULL;

	if (no_to_all)
		qprintf("\nCounting aliases with nonexistent delivery userid's...\n");
	if (yes_to_all)
		qprintf("\nRemoving aliases with nonexistent delivery userid's...\n");

	aliases = auth_get_known_aliases();
	aliases = g_list_dedup(aliases, (GCompareFunc)strcmp, TRUE);
	aliases = g_list_first(aliases);
	while (aliases) {
		char deliver_to[21];
		GList *dangling = find_dangling_aliases(aliases->data);

		dangling = g_list_first(dangling);
		while (dangling) {
			count++;
			g_snprintf(deliver_to, 21, "%" PRIu64 "", *(uint64_t *)dangling->data);
			qverbosef("Dangling alias [%s] delivers to nonexistent user [%s]\n",
				(char *)aliases->data, deliver_to);
			if (yes_to_all) {
				if (auth_removealias_ext(aliases->data, deliver_to) < 0) {
					qerrorf("Error: could not remove alias [%s] deliver to [%s] \n",
						(char *)aliases->data, deliver_to);
					serious_errors = 1;
					result = -1;
				}
			}
			if (!g_list_next(dangling))
				break;
			dangling = g_list_next(dangling);
		}
		g_list_destroy(g_list_first(dangling));

		if (! g_list_next(aliases))
			break;
		aliases = g_list_next(aliases);
	}
	g_list_destroy(g_list_first(aliases));

	if (count > 0) {
		qerrorf("Ok. Found [%d] dangling aliases.\n", count);
		has_errors = 1;
	} else {
		qprintf("Ok. Found [%d] dangling aliases.\n", count);
	}

	return result;
}
Beispiel #2
0
void client_session_reset(ClientSession_t * session)
{
	dsnuser_free_list(session->rcpt);
	session->rcpt = NULL;

	g_list_destroy(session->from);
	session->from = NULL;

	if (session->apop_stamp) {
		g_free(session->apop_stamp);
		session->apop_stamp = NULL;
	}

	if (session->username) {
		g_free(session->username);
		session->username = NULL;
	}

	if (session->password) {
		g_free(session->password);
		session->password = NULL;
	}

	session->state = CLIENTSTATE_INITIAL_CONNECT;

	client_session_reset_parser(session);
}
Beispiel #3
0
static long long int _update_recent(volatile GList *slices, uint64_t seq)
{
	INIT_QUERY;
	Connection_T c;
	volatile long long int count = 0;

	if (! (slices = g_list_first(slices)))
		return count;

	c = db_con_get();
	TRY
		db_begin_transaction(c);
		while (slices) {
			Connection_execute(c, "UPDATE %smessages SET recent_flag = 0, seq = %" PRIu64 
					" WHERE recent_flag = 1 AND seq < %" PRIu64 
					" AND message_idnr IN (%s)", 
					DBPFX, seq, seq, (gchar *)slices->data);
			count += Connection_rowsChanged(c);
			if (! g_list_next(slices)) break;
			slices = g_list_next(slices);
		}
		db_commit_transaction(c);
	CATCH(SQLException)
		LOG_SQLERROR;
		count = DM_EQUERY;
		db_rollback_transaction(c);
	FINALLY
		db_con_close(c);
		g_list_destroy(slices);
	END_TRY;

	return count;
}
Beispiel #4
0
static void db_session_cleanup(ClientSession_t * session_ptr)
{
	/* cleanups a session 
	   removes a list and all references */
	session_ptr->totalsize = 0;
	session_ptr->virtual_totalsize = 0;
	session_ptr->totalmessages = 0;
	session_ptr->virtual_totalmessages = 0;
	g_list_destroy(session_ptr->messagelst);
}
Beispiel #5
0
int auth_check_user_ext(const char *username, GList **userids, GList **fwds, int checks)
{
	int occurences = 0;
	GList *d = NULL;
	char *endptr;
	uint64_t id, *uid;

	if (checks > 20) {
		TRACE(TRACE_ERR,"too many checks. Possible loop detected.");
		return 0;
	}

	TRACE(TRACE_DEBUG, "[%d] checking user [%s] in alias table", checks, username);

	d = user_get_deliver_to(username);

	if (! d) {
		if (checks == 0) {
			TRACE(TRACE_DEBUG, "user %s not in aliases table", username);
			return 0;
		}
		/* found the last one, this is the deliver to
		 * but checks needs to be bigger then 0 because
		 * else it could be the first query failure */
		id = strtoull(username, &endptr, 10);
		if (*endptr == 0) {
			/* numeric deliver-to --> this is a userid */
			uid = g_new0(uint64_t,1);
			*uid = id;
			*(GList **)userids = g_list_prepend(*(GList **)userids, uid);

		} else {
			*(GList **)fwds = g_list_prepend(*(GList **)fwds, g_strdup(username));
		}
		TRACE(TRACE_DEBUG, "adding [%s] to deliver_to address", username);
		return 1;
	} 

	while (d) {
		/* do a recursive search for deliver_to */
		char *deliver_to = (char *)d->data;
		TRACE(TRACE_DEBUG, "checking user %s to %s", username, deliver_to);

		occurences += auth_check_user_ext(deliver_to, userids, fwds, checks+1);

		if (! g_list_next(d)) break;
		d = g_list_next(d);
	}

	g_list_destroy(d);

	return occurences;
}
Beispiel #6
0
void client_session_reset_parser(ClientSession_t *session)
{
	session->parser_state = FALSE;
	session->command_type = FALSE;
	if (session->rbuff) {
		g_string_truncate(session->rbuff,0);
		g_string_maybe_shrink(session->rbuff);
	}

	if (session->args) {
		g_list_destroy(session->args);
		session->args = NULL;
	}
}
Beispiel #7
0
void dm_ldap_freeresult(GList *entlist)
{
	GList *fldlist, *attlist;
	entlist = g_list_first(entlist);
	while (entlist) {
		fldlist = entlist->data;
		while(fldlist) {
			attlist = fldlist->data;
			g_list_destroy(attlist);
			if (! g_list_next(fldlist)) break;
			fldlist = g_list_next(fldlist);
		}
		g_list_free(g_list_first(fldlist));

		if (! g_list_next(entlist)) break;
		entlist = g_list_next(entlist);
	}
	g_list_free(g_list_first(entlist));
}
static int do_rfc_size(void)
{
	time_t start, stop;
	GList *lost = NULL;

	if (no_to_all) {
		qprintf("\nChecking DBMAIL for rfcsize field...\n");
	}
	if (yes_to_all) {
		qprintf("\nRepairing DBMAIL for rfcsize field...\n");
	}
	time(&start);

	if (db_icheck_rfcsize(&lost) < 0) {
		qerrorf("Failed. An error occured. Please check log.\n");
		serious_errors = 1;
		return -1;
	}

	if (g_list_length(lost) > 0) {
		qerrorf("Ok. Found [%d] missing rfcsize values.\n", g_list_length(lost));
		has_errors = 1;
	} else {
		qprintf("Ok. Found [%d] missing rfcsize values.\n", g_list_length(lost));
	}

	if (yes_to_all) {
		if (db_update_rfcsize(lost) < 0) {
			qerrorf("Error setting the rfcsize values");
			has_errors = 1;
		}
	}

	g_list_destroy(lost);

	time(&stop);
	qverbosef("--- checking rfcsize field took %g seconds\n",
	       difftime(stop, start));
	
	return 0;

}
Beispiel #9
0
END_TEST

START_TEST(test_dbmail_message_get_header_addresses)
{
	GList * result;
	GString *s;
	DbmailMessage *m;

	s = g_string_new(multipart_message);
	m = dbmail_message_new();
	m = dbmail_message_init_with_string(m,s);
	
	result = dbmail_message_get_header_addresses(m, "Cc");
	result = g_list_first(result);

	fail_unless(result != NULL, "dbmail_message_get_header_addresses failed");
	fail_unless(g_list_length(result)==2,"dbmail_message_get_header_addresses failed");
	fail_unless(strcmp((char *)result->data,"*****@*****.**")==0, "dbmail_message_get_header_addresses failed");

	g_list_destroy(result);
	dbmail_message_free(m);
	g_string_free(s,TRUE);
}
Beispiel #10
0
int do_check_integrity(void)
{
	time_t start, stop;
	GList *lost = NULL;
	const char *action;
	gboolean cleanup;
	long count = 0;

	if (yes_to_all) {
		action = "Repairing";
		cleanup = TRUE;
	} else {
		action = "Checking";
		cleanup = FALSE;
	}

	qprintf("\n%s DBMAIL message integrity...\n", action);

	/* This is what we do:
	 3. Check for loose physmessages
	 4. Check for loose partlists
	 5. Check for loose mimeparts
	 */

	/* part 3 */
	start = stop;
	qprintf("\n%s DBMAIL physmessage integrity...\n", action);
	if ((count = db_icheck_physmessages(cleanup)) < 0) {
		qerrorf("Failed. An error occurred. Please check log.\n");
		serious_errors = 1;
		return -1;
	}
	if (count > 0) {
		qerrorf("Ok. Found [%ld] unconnected physmessages.\n", count);
		if (cleanup) {
			qerrorf("Ok. Orphaned physmessages deleted.\n");
		}
	} else {
		qprintf("Ok. Found [%ld] unconnected physmessages.\n", count);
	}

	time(&stop);
	qverbosef("--- %s unconnected physmessages took %g seconds\n",
		action, difftime(stop, start));
	/* end part 3 */

	/* part 4 */
	start = stop;
	qprintf("\n%s DBMAIL partlists integrity...\n", action);
	if ((count = db_icheck_partlists(cleanup)) < 0) {
		qerrorf("Failed. An error occurred. Please check log.\n");
		serious_errors = 1;
		return -1;
	}
	if (count > 0) {
		qerrorf("Ok. Found [%ld] unconnected partlists.\n", count);
		if (cleanup) {
			qerrorf("Ok. Orphaned partlists deleted.\n");
		}
	} else {
		qprintf("Ok. Found [%ld] unconnected partlists.\n", count);
	}

	time(&stop);
	qverbosef("--- %s unconnected partlists took %g seconds\n",
		action, difftime(stop, start));
	/* end part 4 */

	/*  part 5 */
	start = stop;
	qprintf("\n%s DBMAIL mimeparts integrity...\n", action);
	if ((count = db_icheck_mimeparts(cleanup)) < 0) {
		qerrorf("Failed. An error occurred. Please check log.\n");
		serious_errors = 1;
		return -1;
	}
	if (count > 0) {
		qerrorf("Ok. Found [%ld] unconnected mimeparts.\n", count);
		if (cleanup) {
			qerrorf("Ok. Orphaned mimeparts deleted.\n");
		}
	} else {
		qprintf("Ok. Found [%ld] unconnected mimeparts.\n", count);
	}

	time(&stop);
	qverbosef("--- %s unconnected mimeparts took %g seconds\n",
		action, difftime(stop, start));
	/* end part 5 */

	g_list_destroy(lost);
	lost = NULL;

	time(&stop);
	qverbosef("--- %s block integrity took %g seconds\n", action, difftime(stop, start));
	/* end part 6 */

	return 0;
}
Beispiel #11
0
//--------------------------------------------------------------------------------------//
void Http_getUsers(T R)
{
	struct evbuffer *buf;
	char *username = NULL;
	uint64_t id = 0;

	if (Request_getId(R)) {
		/* 
		 * id can be specified both by name and number
		 *
		 * C < /users/testuser1
		 * C < /users/123
		 *
		 */

		if ((id = strtoull(Request_getId(R), NULL, 10)))
			username = auth_get_userid(id);
		else if (auth_user_exists(Request_getId(R), &id))
			username = g_strdup(Request_getId(R));

		if (! (username && id))
			Request_error(R, HTTP_NOTFOUND, "User not found");
	}

	buf = evbuffer_new();
	if (Request_getMethod(R) == NULL) {
		GList *users = NULL;

		if (username) {
			MailboxState_T M;
			const char *mailbox;
			uint64_t mboxid;
			/* 
			 * retrieve user meta-data
			 * C < /users/testuser1

			 * create/delete mailbox for user
			 * POST C < /users/testuser1

			 */

			if ((mailbox = evhttp_find_header(Request_getPOST(R),"create"))) {
				const char *message;

				if (db_mailbox_create_with_parents(mailbox, BOX_COMMANDLINE, id, &mboxid, &message)) {
					Request_error(R, HTTP_BADREQUEST, message);
					evbuffer_free(buf);
					return;
				}
			}
			if ((mailbox = evhttp_find_header(Request_getPOST(R),"delete"))) {

				int access;

				/* check if there is an attempt to delete inbox */
				if (MATCH(mailbox, "INBOX")) {
					Request_error(R, HTTP_BADREQUEST, "NO cannot delete special mailbox INBOX");
					evbuffer_free(buf);
					return;
				}

				if (! (db_findmailbox(mailbox, id, &mboxid)) ) {
					Request_error(R, HTTP_NOTFOUND, "NO mailbox doesn't exists");
					evbuffer_free(buf);
					return;
				}

				/* Check if the user has ACL delete rights to this mailbox */
				M = MailboxState_new(mboxid);
				access = acl_has_right(M, id, ACL_RIGHT_DELETE);
				if (access != 1) {
					Request_error(R, HTTP_BADREQUEST, "NO permission denied");
					evbuffer_free(buf);
					return;
				}

				/* ok remove mailbox */
				if (db_delete_mailbox(mboxid, 0, 1)) {
					Request_error(R, HTTP_SERVUNAVAIL, "NO delete failed");
					evbuffer_free(buf);
					return;
				}
			}


			users = g_list_append_printf(users, "%s", username);
		} else {
			/* 
			 * list all users
			 * C < /users/
			 *
			 * create,edit,delete user
			 * POST C < /users/
			 */

			const char *user = NULL;

			if ((user = evhttp_find_header(Request_getPOST(R),"create"))) {
				const char *password, *encoding, *quota;
			       	password = evhttp_find_header(Request_getPOST(R), "password");
			       	encoding = evhttp_find_header(Request_getPOST(R), "encoding");
			       	quota    = evhttp_find_header(Request_getPOST(R), "quota");
				TRACE(TRACE_DEBUG, "create user: [%s] password: [%s] encoding [%s] quota [%s]", 
						user, password, encoding, quota);

			} else if ((user = evhttp_find_header(Request_getPOST(R),"edit"))) {
				TRACE(TRACE_DEBUG, "edit user: [%s]", user);

			} else if ((user = evhttp_find_header(Request_getPOST(R),"delete"))) {
				TRACE(TRACE_DEBUG, "delete user: [%s]", user);
			}

			users = auth_get_known_users();
		}

		Request_setContentType(R,"application/json; charset=utf-8");
		evbuffer_add_printf(buf, "{\"users\": {\n");
		while(users->data) {
			uint64_t id;
			if (auth_user_exists((char *)users->data, &id))
				evbuffer_add_printf(buf, "    \"%lu\":{\"name\":\"%s\"}", id, (char *)users->data);
			if (! g_list_next(users)) break;
			users = g_list_next(users);
			evbuffer_add_printf(buf,",\n");
		}
		evbuffer_add_printf(buf, "\n}}\n");
		g_list_destroy(users);

	} else if (MATCH(Request_getMethod(R),"mailboxes")) {
		GList *mailboxes = NULL;

		if (! username) {
			Request_error(R, HTTP_NOTFOUND, "User not found");
			evbuffer_free(buf);
			return;
		}

		/*
		 * list mailboxes for user
		 * GET C < /users/testuser1/mailboxes
		 *
		 */

		db_findmailbox_by_regex(id, "*", &mailboxes, FALSE);

		Request_setContentType(R,"application/json; charset=utf-8");
		evbuffer_add_printf(buf, "{\"mailboxes\": {\n");
		while (mailboxes->data) {
			MailboxState_T b = MailboxState_new(*((uint64_t *)mailboxes->data));
			MailboxState_setOwner(b, id);
			//if (MailboxState_reload(b) == DM_SUCCESS)
			evbuffer_add_printf(buf, "    \"%lu\":{\"name\":\"%s\",\"exists\":%u}", MailboxState_getId(b), MailboxState_getName(b), MailboxState_getExists(b));
			MailboxState_free(&b);
			if (! g_list_next(mailboxes)) break;
			mailboxes = g_list_next(mailboxes);
			evbuffer_add_printf(buf,",\n");
		}
		evbuffer_add_printf(buf, "\n}}\n");
	} 

	if (EVBUFFER_LENGTH(buf))
		Request_send(R, HTTP_OK, "OK", buf);
	else		
		Request_error(R, HTTP_SERVUNAVAIL, "Server error");

	if (username) g_free(username);
	evbuffer_free(buf);
}
Beispiel #12
0
int tims(ClientSession_t *session)
{
	/* returns values:
	 *  0 to quit
	 * -1 on failure
	 *  1 on success */
	
	char *arg;
	size_t scriptlen = 0;
	int ret;
	char *script = NULL, *scriptname = NULL;
	sort_result_t *sort_result = NULL;
	clientbase_t *ci = session->ci;

	TRACE(TRACE_DEBUG,"[%p] [%d][%s]", session, session->command_type, commands[session->command_type]);
	switch (session->command_type) {
	case TIMS_LOUT:
		ci_write(ci, "OK \"Bye.\"\r\n");
		session->state = QUIT;
		return 1;
		
	case TIMS_STLS:
		ci_write(ci, "NO\r\n");
		return 1;
		
	case TIMS_CAPA:
		send_greeting(session);
		return 1;
		
	case TIMS_AUTH:
		/* We currently only support plain authentication,
		 * which means that the command we accept will look
		 * like this: Authenticate "PLAIN" "base64-password"
		 * */
		session->args = g_list_first(session->args);
		if (! (session->args && session->args->data))
			return 1;

		arg = (char *)session->args->data;
		if (strcasecmp(arg, "PLAIN") == 0) {
			int i = 0;
			u64_t useridnr;
			if (! g_list_next(session->args))
				return tims_error(session, "NO \"Missing argument.\"\r\n");	
			session->args = g_list_next(session->args);
			arg = (char *)session->args->data;

			char **tmp64 = NULL;

			tmp64 = base64_decodev(arg);
			if (tmp64 == NULL)
				return tims_error(session, "NO \"SASL decode error.\"\r\n");
			for (i = 0; tmp64[i] != NULL; i++)
				;
			if (i < 3)
				tims_error(session, "NO \"Too few encoded SASL arguments.\"\r\n");

			/* The protocol specifies that the base64 encoding
			 * be made up of three parts: proxy, username, password
			 * Between them are NULLs, which are conveniently encoded
			 * by the base64 process... */
			if (auth_validate(ci, tmp64[1], tmp64[2], &useridnr) == 1) {
				ci_authlog_init(ci, THIS_MODULE, tmp64[1], AUTHLOG_ACT);

				ci_write(ci, "OK\r\n");
				session->state = AUTH;
				session->useridnr = useridnr;
				session->username = g_strdup(tmp64[1]);
				session->password = g_strdup(tmp64[2]);

				client_session_set_timeout(session, server_conf->timeout);

			} else {
				ci_authlog_init(ci, THIS_MODULE, tmp64[1], AUTHLOG_ERR);
				g_strfreev(tmp64);
				return tims_error(session, "NO \"Username or password incorrect.\"\r\n");
			}
			g_strfreev(tmp64);
		} else
			return tims_error(session, "NO \"Authentication scheme not supported.\"\r\n");

		return 1;

	case TIMS_PUTS:
		if (session->state != AUTH) {
			ci_write(ci, "NO \"Please authenticate first.\"\r\n");
			break;
		}
		
		session->args = g_list_first(session->args);
		if (! (session->args && session->args->data))
			return 1;

		scriptname = (char *)session->args->data;
		session->args = g_list_next(session->args);
		assert(session->args);

		script = (char *)session->args->data;

		scriptlen = strlen(script);
		TRACE(TRACE_INFO, "Client sending script of length [%ld]", scriptlen);
		if (scriptlen >= UINT_MAX)
			return tims_error(session, "NO \"Invalid script length.\"\r\n");

		if (dm_sievescript_quota_check(session->useridnr, scriptlen))
			return tims_error(session, "NO \"Script exceeds available space.\"\r\n");

		/* Store the script temporarily,
		 * validate it, then rename it. */
		if (dm_sievescript_add(session->useridnr, "@!temp-script!@", script)) {
			dm_sievescript_delete(session->useridnr, "@!temp-script!@");
			return tims_error(session, "NO \"Error inserting script.\"\r\n");
		}
		
		sort_result = sort_validate(session->useridnr, "@!temp-script!@");
		if (sort_result == NULL) {
			dm_sievescript_delete(session->useridnr, "@!temp-script!@");
			return tims_error(session, "NO \"Error inserting script.\"\r\n");
		} else if (sort_get_error(sort_result) > 0) {
			dm_sievescript_delete(session->useridnr, "@!temp-script!@");
			return tims_error(session, "NO \"Script error: %s.\"\r\n", sort_get_errormsg(sort_result));
		} 
		/* According to the draft RFC, a script with the same
		 * name as an existing script should [atomically] replace it. */
		if (dm_sievescript_rename(session->useridnr, "@!temp-script!@", scriptname))
			return tims_error(session, "NO \"Error inserting script.\"\r\n");

		ci_write(ci, "OK \"Script successfully received.\"\r\n");

		break;
		
	case TIMS_SETS:
		if (session->state != AUTH) {
			ci_write(ci, "NO \"Please authenticate first.\"\r\n");
			break;
		}
		

		scriptname = NULL;

		session->args = g_list_first(session->args);
		if ((session->args && session->args->data))
			scriptname = (char *)session->args->data;

		if (strlen(scriptname)) {
			if (! dm_sievescript_activate(session->useridnr, scriptname))
				ci_write(ci, "NO \"Error activating script.\"\r\n");
			else
				ci_write(ci, "OK \"Script activated.\"\r\n");
		} else {
			ret = dm_sievescript_get(session->useridnr, &scriptname);
			if (scriptname == NULL) {
				ci_write(ci, "OK \"No scripts are active at this time.\"\r\n");
			} else {
				if (! dm_sievescript_deactivate(session->useridnr, scriptname))
					ci_write(ci, "NO \"Error deactivating script.\"\r\n");
				else
					ci_write(ci, "OK \"All scripts deactivated.\"\r\n");
				g_free(scriptname);
			}
		}
		return 1;
		
	case TIMS_GETS:
		if (session->state != AUTH) {
			ci_write(ci, "NO \"Please authenticate first.\"\r\n");
			break;
		}
		
		session->args = g_list_first(session->args);
		if (! (session->args && session->args->data))
			return 1;

		scriptname = (char *)session->args->data;

		if (! strlen(scriptname))
			return tims_error(session, "NO \"Script name required.\"\r\n");

		ret = dm_sievescript_getbyname(session->useridnr, scriptname, &script);
		if (script == NULL) {
			return tims_error(session, "NO \"Script not found.\"\r\n");
		} else if (ret < 0) {
			g_free(script);
			return tims_error(session, "NO \"Internal error.\"\r\n");
		} else {
			ci_write(ci, "{%u+}\r\n", (unsigned int)strlen(script));
			ci_write(ci, "%s\r\n", script);
			ci_write(ci, "OK\r\n");
			g_free(script);
		}
		return 1;
		
	case TIMS_DELS:
		if (session->state != AUTH) {
			ci_write(ci, "NO \"Please authenticate first.\"\r\n");
			break;
		}
		
		session->args = g_list_first(session->args);
		if (! (session->args && session->args->data))
			return 1;

		scriptname = (char *)session->args->data;

		if (! strlen(scriptname))
			return tims_error(session, "NO \"Script name required.\"\r\n");

		if (! dm_sievescript_delete(session->useridnr, scriptname))
			return tims_error(session, "NO \"Error deleting script.\"\r\n");
		else
			ci_write(ci, "OK \"Script deleted.\"\r\n", scriptname);

		return 1;

	case TIMS_SPAC:
		if (session->state != AUTH) {
			ci_write(ci, "NO \"Please authenticate first.\"\r\n");
			break;
		}

		// Command is in format: HAVESPACE "scriptname" 12345
		// TODO: this is a fake
		if (dm_sievescript_quota_check(session->useridnr, 12345) == DM_SUCCESS)
			ci_write(ci, "OK (QUOTA)\r\n");
		else
			ci_write(ci, "NO (QUOTA) \"Quota exceeded\"\r\n");
		return 1;
		
	case TIMS_LIST:
		if (session->state != AUTH) {
			ci_write(ci, "NO \"Please authenticate first.\"\r\n");
			break;
		}
		
		GList *scriptlist = NULL;

		if (dm_sievescript_list (session->useridnr, &scriptlist) < 0) {
			ci_write(ci, "NO \"Internal error.\"\r\n");
		} else {
			if (g_list_length(scriptlist) == 0) {
				/* The command hasn't failed, but there aren't any scripts */
				ci_write(ci, "OK \"No scripts found.\"\r\n");
			} else {
				scriptlist = g_list_first(scriptlist);
				while (scriptlist) {
					sievescript_info_t *info = (sievescript_info_t *) scriptlist->data;
					ci_write(ci, "\"%s\"%s\r\n", info->name, (info-> active == 1 ?  " ACTIVE" : ""));
					if (! g_list_next(scriptlist)) break;
					scriptlist = g_list_next(scriptlist);
				}
				ci_write(ci, "OK\r\n");
			}
			g_list_destroy(scriptlist);
		}
		return 1;
		
	default:
		return tims_error(session, "NO \"What are you trying to say here?\"\r\n");
	}

	if (sort_result)
		sort_free_result(sort_result);
	
	return 1;
}
Beispiel #13
0
static void MessageInfo_free(MessageInfo *m)
{
	g_list_destroy(m->keywords);
	g_free(m);
}
Beispiel #14
0
GTree * MailboxState_get_set(MailboxState_T M, const char *set, gboolean uid)
{
	GTree *inset, *a, *b;
	GList *sets = NULL;
	GString *t;
	uint64_t lo = 0, hi = 0;
	gboolean error = FALSE;

	if (uid)
		inset = MailboxState_getIds(M);
	else
		inset = MailboxState_getMsn(M);

	a = g_tree_new_full((GCompareDataFunc)ucmpdata,NULL, (GDestroyNotify)uint64_free, (GDestroyNotify)uint64_free);
	b = g_tree_new_full((GCompareDataFunc)ucmpdata,NULL, (GDestroyNotify)uint64_free, (GDestroyNotify)uint64_free);

	if (! uid) {
		lo = 1;
		hi = MailboxState_getExists(M);
	} else {
		GList *ids = g_tree_keys(inset);
		if (ids) {
			ids = g_list_last(ids);
			hi = *((uint64_t *)ids->data);
			ids = g_list_first(ids);
			lo = *((uint64_t *)ids->data);
			g_list_free(g_list_first(ids));
		}
	}

	t = g_string_new(set);
	sets = g_string_split(t,",");
	g_string_free(t,TRUE);

	sets = g_list_first(sets);
	while(sets) {
		uint64_t l = 0, r = 0;
		
		char *rest = (char *)sets->data;

		if (strlen(rest) < 1) break;

		if (g_tree_nnodes(inset) == 0) { // empty box
			if (rest[0] == '*') {
				uint64_t *k = mempool_pop(small_pool, sizeof(uint64_t));
				uint64_t *v = mempool_pop(small_pool, sizeof(uint64_t));

				*k = 1;
				*v = MailboxState_getUidnext(M);

				g_tree_insert(b, k, v);
			} else {
				if (! (l = dm_strtoull(sets->data, &rest, 10))) {
					error = TRUE;
					break;
				}
				if (rest[0]) {
					if (rest[0] != ':') {
						error = TRUE;
						break;
					}
					rest++;
					if ((rest[0] != '*') && (! dm_strtoull(rest, NULL, 10))) {
						error = TRUE;
						break;
					}
				}
				uint64_t *k = mempool_pop(small_pool, sizeof(uint64_t));
				uint64_t *v = mempool_pop(small_pool, sizeof(uint64_t));

				*k = 1;
				*v = MailboxState_getUidnext(M);

				g_tree_insert(b, k, v);
			}
		} else {
			if (rest[0] == '*') {
				l = hi;
				r = l;
				if (strlen(rest) > 1)
					rest++;
			} else {
				if (! (l = dm_strtoull(sets->data,&rest,10))) {
					error = TRUE;
					break;
				}

				if (l == 0xffffffff) l = hi; // outlook

				l = max(l,lo);
				r = l;
			}
			
			if (rest[0]==':') {
				if (strlen(rest)>1) rest++;
				if (rest[0] == '*') r = hi;
				else {
					if (! (r = dm_strtoull(rest,NULL,10))) {
						error = TRUE;
						break;
					}

					if (r == 0xffffffff) r = hi; // outlook
				}
				
				if (!r) break;
			}
		
			if (! (l && r)) break;

			find_range(inset, min(l,r), max(l,r), a, uid);

			if (g_tree_merge(b,a,IST_SUBSEARCH_OR)) {
				error = TRUE;
				TRACE(TRACE_ERR, "cannot compare null trees");
				break;
			}
		}

		if (! g_list_next(sets)) break;
		sets = g_list_next(sets);
	}

	g_list_destroy(sets);

	if (a) g_tree_destroy(a);

	if (error) {
		g_tree_destroy(b);
		b = NULL;
		TRACE(TRACE_DEBUG, "return NULL");
	}

	return b;
}
Beispiel #15
0
int do_check_integrity(void)
{
	time_t start, stop;
	GList *lost = NULL;
	const char *action;
	gboolean cleanup;
	long count = 0;

	if (yes_to_all) {
		action = "Repairing";
		cleanup = TRUE;
	} else {
		action = "Checking";
		cleanup = FALSE;
	}

	qprintf("\n%s DBMAIL message integrity...\n", action);

	/* This is what we do:
	 3. Check for loose physmessages
	 4. Check for loose partlists
	 5. Check for loose mimeparts
	 6. Check for loose headernames
	 7. Check for loose headervalues
	 */

	/* part 3 */
	time(&start);
	qprintf("\n%s DBMAIL physmessage integrity...\n", action);
	if ((count = db_icheck_physmessages(cleanup)) < 0) {
		qerrorf("Failed. An error occurred. Please check log.\n");
		serious_errors = 1;
		return -1;
	}
	if (count > 0) {
		qerrorf("Ok. Found [%ld] unconnected physmessages.\n", count);
		if (cleanup) {
			qerrorf("Ok. Orphaned physmessages deleted.\n");
		}
	} else {
		qprintf("Ok. Found [%ld] unconnected physmessages.\n", count);
	}

	time(&stop);
	qverbosef("--- %s unconnected physmessages took %g seconds\n",
		action, difftime(stop, start));
	/* end part 3 */

	/* part 4 */
	start = stop;
	qprintf("\n%s DBMAIL partlists integrity...\n", action);
	if ((count = db_icheck_partlists(cleanup)) < 0) {
		qerrorf("Failed. An error occurred. Please check log.\n");
		serious_errors = 1;
		return -1;
	}
	if (count > 0) {
		qerrorf("Ok. Found [%ld] unconnected partlists.\n", count);
		if (cleanup) {
			qerrorf("Ok. Orphaned partlists deleted.\n");
		}
	} else {
		qprintf("Ok. Found [%ld] unconnected partlists.\n", count);
	}

	time(&stop);
	qverbosef("--- %s unconnected partlists took %g seconds\n",
		action, difftime(stop, start));
	/* end part 4 */

	/*  part 5 */
	start = stop;
	qprintf("\n%s DBMAIL mimeparts integrity...\n", action);
	if ((count = db_icheck_mimeparts(cleanup)) < 0) {
		qerrorf("Failed. An error occurred. Please check log.\n");
		serious_errors = 1;
		return -1;
	}
	if (count > 0) {
		qerrorf("Ok. Found [%ld] unconnected mimeparts.\n", count);
		if (cleanup) {
			qerrorf("Ok. Orphaned mimeparts deleted.\n");
		}
	} else {
		qprintf("Ok. Found [%ld] unconnected mimeparts.\n", count);
	}

	time(&stop);
	qverbosef("--- %s unconnected mimeparts took %g seconds\n",
		action, difftime(stop, start));
	/* end part 5 */

	/* part 6 */
        Field_T config;
	bool cache_readonly = false;
	config_get_value("header_cache_readonly", "DBMAIL", config);
	if (strlen(config)) {
		if (MATCH(config, "true") || MATCH(config, "yes")) {
			cache_readonly = true;
		}
	}

        if (! cache_readonly) {
		start = stop;
		qprintf("\n%s DBMAIL headernames integrity...\n", action);
		if ((count = db_icheck_headernames(cleanup)) < 0) {
			qerrorf("Failed. An error occurred. Please check log.\n");
			serious_errors = 1;
			return -1;
		}

		qprintf("Ok. Found [%ld] unconnected headernames.\n", count);
		if (count > 0 && cleanup) {
			qerrorf("Ok. Orphaned headernames deleted.\n");
		}

		time(&stop);
		qverbosef("--- %s unconnected headernames took %g seconds\n",
			action, difftime(stop, start));
	}
	/* end part 6 */

	/* part 7 */
	start = stop;
	qprintf("\n%s DBMAIL headervalues integrity...\n", action);
	if ((count = db_icheck_headervalues(cleanup)) < 0) {
		qerrorf("Failed. An error occurred. Please check log.\n");
		serious_errors = 1;
		return -1;
	}

	qprintf("Ok. Found [%ld] unconnected headervalues.\n", count);
	if (count > 0 && cleanup) {
		qerrorf("Ok. Orphaned headervalues deleted.\n");
	}

	time(&stop);
	qverbosef("--- %s unconnected headervalues took %g seconds\n",
		action, difftime(stop, start));
	/* end part 7 */

	g_list_destroy(lost);
	lost = NULL;

	time(&stop);
	qverbosef("--- %s block integrity took %g seconds\n", action, difftime(stop, start));

	return 0;
}
Beispiel #16
0
static int do_export(char *user, char *base_mailbox, char *basedir, char *outfile, char *search, int delete_after_dump, int recursive)
{
	u64_t user_idnr = 0, owner_idnr = 0, mailbox_idnr = 0;
	char *dumpfile = NULL, *mailbox = NULL, *search_mailbox = NULL, *dir = NULL;
	GList *children = NULL;
	int result = 0;

	/* Verify the existence of this user */
	if (! auth_user_exists(user, &user_idnr)) {
		qerrorf("Error: user [%s] does not exist.\n", user);
		result = -1;
		goto cleanup;
	}

	mailbox = g_new0(char, IMAP_MAX_MAILBOX_NAMELEN);

	if (!base_mailbox) {
		/* Always recursive without a mailbox base */
		search_mailbox = g_strdup("*");
	} else if (recursive) {
		/* Base and everything below */
		search_mailbox = g_strdup_printf("%s*", base_mailbox);
	} else if (!recursive) {
		/* Should yield same results as plain db_findmailbox */
		search_mailbox = g_strdup_printf("%s", base_mailbox);
	}

	/* FIXME: What are the possible error conditions here? */
	db_findmailbox_by_regex(user_idnr, search_mailbox, &children, 0);

	/* Decision process for basedir vs. outfile:
	 *   If we're dumping one mailbox for one user, it goes to
	 *   stdout.  If we've been given -o -, dump everything to
	 *   stdout (e.g., one giant mbox).  If we've been given foo
	 */

	if (!outfile && !basedir) {
		/* Default is to use basedir of . */
		basedir = ".";
	} else if (outfile) {
		/* Everything goes into this one file */
		dumpfile = outfile;
	}

	children = g_list_first(children);

	qerrorf("Exporting [%u] mailboxes for [%s]\n", g_list_length(children), user);

	while (children) {
		mailbox_idnr = *(u64_t *)children->data;
		db_getmailboxname(mailbox_idnr, user_idnr, mailbox);			
		if (! db_get_mailbox_owner(mailbox_idnr, &owner_idnr)) {
			qerrorf("Error checking mailbox ownership");
			goto cleanup;
		}
		if (owner_idnr == user_idnr) {
			if (basedir) {
				/* Prepare the directory */
				dumpfile = g_strdup_printf("%s/%s/%s.mbox", basedir, user, mailbox);

				dir = g_path_get_dirname(dumpfile);
				if (g_mkdir_with_parents(dir, 0700)) {
					qerrorf("can't create directory [%s]\n", dir);
					result = -1;
					goto cleanup;
				}
			}

			qerrorf(" export mailbox %s -> %s\n", mailbox, dumpfile);
			if ((result = mailbox_dump(mailbox_idnr, dumpfile, search, delete_after_dump)) != 0) {
				qerrorf("error exporting mailbox %s -> %s\n", mailbox, dumpfile);
				goto cleanup;
			}

			if (delete_after_dump) db_update("UPDATE %smailboxes SET seq=seq+1 WHERE mailbox_idnr=%d",DBPFX,mailbox_idnr);

			if (basedir) {
				g_free(dir);
				g_free(dumpfile);
			}
		}
		if (! g_list_next(children)) break;
		children = g_list_next(children);
	}

cleanup:
	g_list_destroy(children);
	g_free(search_mailbox);
	g_free(mailbox);

	return result;
}
END_TEST

START_TEST(test_internet_address_list_parse_string)
{
	char * trythese [][2] = { 
		{ "undisclosed-recipients", "((NIL NIL \"undisclosed-recipients\" NIL))"},
		{ "undisclosed-recipients;", "((NIL NIL \"undisclosed-recipients\" NIL))"},
		{ "undisclosed-recipients:", "((NIL NIL \"undisclosed-recipients\" NIL)(NIL NIL NIL NIL))"}, 
		{ "undisclosed-recipients:;", "((NIL NIL \"undisclosed-recipients\" NIL)(NIL NIL NIL NIL))"},
		{ "undisclosed-recipients: ;", "((NIL NIL \"undisclosed-recipients\" NIL)(NIL NIL NIL NIL))"},
		{ NULL, NULL }
		};
	int i;

	for (i = 0; trythese[i][0] != NULL; i++) {

		char *input = trythese[i][0];
		char *expect = trythese[i][1];
		char *t, *result;

		InternetAddressList *alist;
		GList *list = NULL;

		t = imap_cleanup_address(input);
		alist = internet_address_list_parse_string(t);
		g_free(t);
		list = dbmail_imap_append_alist_as_plist(list, alist);
		g_object_unref(alist);
		alist = NULL;

		result = dbmail_imap_plist_as_string(list);

		fail_unless(strcmp(result,expect)==0, "internet_address_list_parse_string failed to generate correct undisclosed-recipients plist "
			"for [%s], expected\n[%s] got\n[%s]", input, expect, result);

		g_list_destroy(list);
		g_free(result);

	}

	char * testlist[][2] = {
		{ "<*****@*****.**>", "((NIL NIL \"i_am_not\" \"broken.org\"))" },
		{ "Break me: <*****@*****.**>", "((NIL NIL \"Break me\" NIL)(NIL NIL \"foo\" \"bar.org\")(NIL NIL NIL NIL))" },
		{ "Joe's Friends: [email protected], [email protected], [email protected];",
			"((NIL NIL \"Joe's Friends\" NIL)(NIL NIL \"mary\" \"joe.com\")"
			"(NIL NIL \"joe\" \"joe.com\")(NIL NIL \"jane\" \"joe.com\")(NIL NIL NIL NIL))" },
		// These have the wrong separator; ms lookout style.
		{ "[email protected];[email protected]", "((NIL NIL \"one\" \"my.dom\")(NIL NIL \"two\" \"my.dom\"))" },
		{ "[email protected]; [email protected]", "((NIL NIL \"one\" \"my.dom\")(NIL NIL \"two\" \"my.dom\"))" },
		{ "Group: [email protected];, [email protected]", "((NIL NIL \"Group\" NIL)(NIL NIL \"one\" \"my.dom\")(NIL NIL NIL NIL)(NIL NIL \"two\" \"my.dom\"))" },
		{ NULL, NULL }
	};

	char *input, *expect;

	for (i = 0; testlist[i][0] != NULL; i++) {
		input = testlist[i][0];
		expect = testlist[i][1];

		InternetAddressList *alist;
		GList *list = NULL;
		char *result;
		int res;
		char *t;
		t = imap_cleanup_address(input);
		alist = internet_address_list_parse_string(t);
		list = dbmail_imap_append_alist_as_plist(list, alist);
		result = dbmail_imap_plist_as_string(list);
		res = strcmp(result, expect);

		fail_unless(res == 0, "dbmail_imap_append_alist_as_plist failed, expected:\n[%s]\ngot:\n[%s]\n", expect, result);

		g_object_unref(alist);
		alist = NULL;
		g_list_destroy(list);
		g_free(result);
		g_free(t);
	}
}
Beispiel #18
0
int main(int argc, char *argv[])
{
	int opt = 0, opt_prev = 0;
	int show_help = 0;
	int result = 0, delete_after_dump = 0, recursive = 0;
	char *user=NULL, *mailbox=NULL, *outfile=NULL, *basedir=NULL, *search=NULL;

	openlog(PNAME, LOG_PID, LOG_MAIL);
	setvbuf(stdout, 0, _IONBF, 0);

	g_mime_init(0);

	/* get options */
	opterr = 0;		/* suppress error message from getopt() */
	while ((opt = getopt(argc, argv,
		"-u:m:o:b:s:dDr" /* Major modes */
		"f:qvVh" /* Common options */ )) != -1) {
		/* The initial "-" of optstring allows unaccompanied
		 * options and reports them as the optarg to opt 1 (not '1') */
		if (opt == 1)
			opt = opt_prev;
		opt_prev = opt;

		switch (opt) {
		/* export specific options */
		case 'u':
			if (optarg && strlen(optarg))
				user = optarg;
			break;

		case 'm':
			if (optarg && strlen(optarg))
				mailbox = optarg;
			break;
		case 'b':
			if (optarg && strlen(optarg))
				basedir = optarg;
			break;
		case 'o':
			if (optarg && strlen(optarg))
				outfile = optarg;
			break;
		case 'd':
			delete_after_dump |= 1;
			break;
		case 'D':
			delete_after_dump |= 2;
			break;
		case 'r':
			recursive = 1;
			break;
		case 's':
			if (optarg && strlen(optarg))
				search = optarg;
			else {
				qerrorf("dbmail-mailbox: -s requires a value\n\n");
				result = 1;
			}
			break;

		/* Common options */
		case 'f':
			if (optarg && strlen(optarg) > 0)
				configFile = optarg;
			else {
				qerrorf("dbmail-mailbox: -f requires a filename\n\n");
				result = 1;
			}
			break;

		case 'h':
			show_help = 1;
			break;

		case 'q':
			/* If we get q twice, be really quiet! */
			if (quiet)
				reallyquiet = 1;
			if (!verbose)
				quiet = 1;
			break;

		case 'v':
			if (!quiet)
				verbose = 1;
			break;

		case 'V':
			/* Show the version and return non-zero. */
			PRINTF_THIS_IS_DBMAIL;
			result = 1;
			break;
		default:
			/* printf("unrecognized option [%c], continuing...\n",optopt); */
			break;
		}

		/* If there's a non-negative return code,
		 * it's time to free memory and bail out. */
		if (result)
			goto freeall;
	}	

	/* If nothing is happening, show the help text. */
	if (!user || (basedir && outfile) || show_help) {
		do_showhelp();
		result = 1;
		goto freeall;
	}
 
	/* read the config file */
        if (config_read(configFile) == -1) {
                qerrorf("Failed. Unable to read config file %s\n", configFile);
                result = -1;
                goto freeall;
        }
                
	SetTraceLevel("DBMAIL");
	GetDBParams();

	/* open database connection */
	if (db_connect() != 0) {
		qerrorf ("Failed. Could not connect to database (check log)\n");
		result = -1;
		goto freeall;
	}

	/* open authentication connection */
	if (auth_connect() != 0) {
		qerrorf("Failed. Could not connect to authentication (check log)\n");
		result = -1;
		goto freeall;
	}

	/* Loop over all user accounts if there's a wildcard. */
	if (strchr(user, '?') || strchr(user, '*')) {
		GList *all_users = auth_get_known_users();
		GList *matching_users = match_glob_list(user, all_users);
		GList *users = g_list_first(matching_users);

		if (!users) {
			qerrorf("Error: no users matching [%s] were found.\n", user);
			g_list_destroy(all_users);
			result = -1;
			goto freeall;
		}

		while (users) {
			result = do_export(users->data, mailbox,
				basedir, outfile, search,
				delete_after_dump, recursive);

			if (!g_list_next(users))
				break;
			users = g_list_next(users);
		}

		g_list_destroy(all_users);
		g_list_destroy(matching_users);
	} else {
		/* No globbing, just run with this one user. */
		result = do_export(user, mailbox,
			basedir, outfile, search,
			delete_after_dump, recursive);
	}

	/* Here's where we free memory and quit.
	 * Be sure that all of these are NULL safe! */
freeall:

	db_disconnect();
	auth_disconnect();
	config_free();
	g_mime_shutdown();

	if (result < 0)
		qerrorf("Command failed.\n");
	return result;
}