solanum/ircd/authd.c
Elizabeth Myers 394b8dde17 authd: allow querying the list of DNS servers.
This was an asston of pain, and it still feels "dirty" as it introduces
an async call where there normally wouldn't be one. Better
implementation more than welcome.
2016-03-08 02:53:25 -06:00

191 lines
4.4 KiB
C

/*
* authd.c: An interface to authd.
* (based somewhat on ircd-ratbox dns.c)
*
* Copyright (C) 2005 Aaron Sethman <androsyn@ratbox.org>
* Copyright (C) 2005-2012 ircd-ratbox development team
* Copyright (C) 2016 William Pitcock <nenolod@dereferenced.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/
#include <stdinc.h>
#include <rb_lib.h>
#include <client.h>
#include <ircd_defs.h>
#include <parse.h>
#include <authd.h>
#include <match.h>
#include <logger.h>
#include <s_conf.h>
#include <client.h>
#include <send.h>
#include <numeric.h>
#include <msg.h>
#include <dns.h>
static int start_authd(void);
static void parse_authd_reply(rb_helper * helper);
static void restart_authd_cb(rb_helper * helper);
rb_helper *authd_helper;
static char *authd_path;
static int
start_authd(void)
{
char fullpath[PATH_MAX + 1];
#ifdef _WIN32
const char *suffix = ".exe";
#else
const char *suffix = "";
#endif
if(authd_path == NULL)
{
snprintf(fullpath, sizeof(fullpath), "%s/authd%s", PKGLIBEXECDIR, suffix);
if(access(fullpath, X_OK) == -1)
{
snprintf(fullpath, sizeof(fullpath), "%s/libexec/charybdis/authd%s",
ConfigFileEntry.dpath, suffix);
if(access(fullpath, X_OK) == -1)
{
ilog(L_MAIN,
"Unable to execute authd in %s or %s/libexec/charybdis",
PKGLIBEXECDIR, ConfigFileEntry.dpath);
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Unable to execute authd in %s or %s/libexec/charybdis",
PKGLIBEXECDIR, ConfigFileEntry.dpath);
return 1;
}
}
authd_path = rb_strdup(fullpath);
}
authd_helper = rb_helper_start("authd", authd_path, parse_authd_reply, restart_authd_cb);
if(authd_helper == NULL)
{
ilog(L_MAIN, "Unable to start authd helper: %s", strerror(errno));
sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unable to start authd helper: %s", strerror(errno));
return 1;
}
ilog(L_MAIN, "authd helper started");
sendto_realops_snomask(SNO_GENERAL, L_ALL, "authd helper started");
rb_helper_run(authd_helper);
return 0;
}
static void
parse_authd_reply(rb_helper * helper)
{
ssize_t len;
int parc;
char dnsBuf[READBUF_SIZE];
char *parv[MAXPARA + 1];
while((len = rb_helper_read(helper, dnsBuf, sizeof(dnsBuf))) > 0)
{
parc = rb_string_to_array(dnsBuf, parv, MAXPARA+1);
switch (*parv[0])
{
case 'E':
if(parc != 5)
{
ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc);
restart_authd();
return;
}
dns_results_callback(parv[1], parv[2], parv[3], parv[4]);
break;
case 'X':
case 'Y':
case 'Z':
if(parc < 3)
{
ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc);
restart_authd();
return;
}
/* Select by type */
switch(*parv[2])
{
case 'D':
/* parv[0] conveys status */
if(parc < 4)
{
ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc);
restart_authd();
return;
}
dns_stats_results_callback(parv[1], parv[0], parc - 3, (const char **)&parv[3]);
break;
default:
break;
}
break;
default:
break;
}
}
}
void
init_authd(void)
{
if(start_authd())
{
ilog(L_MAIN, "Unable to start authd helper: %s", strerror(errno));
exit(0);
}
}
static void
restart_authd_cb(rb_helper * helper)
{
ilog(L_MAIN, "authd: restart_authd_cb called, authd died?");
sendto_realops_snomask(SNO_GENERAL, L_ALL, "authd: restart_authd_cb called, authd died?");
if(helper != NULL)
{
rb_helper_close(helper);
authd_helper = NULL;
}
start_authd();
}
void
restart_authd(void)
{
restart_authd_cb(authd_helper);
}
void
rehash_authd(void)
{
rb_helper_write(authd_helper, "R");
}
void
check_authd(void)
{
if(authd_helper == NULL)
restart_authd();
}