~rcr/rirc

491e48ce4d1d858787fa8139cd3425b948a4d0a8 — Richard Robbins a month ago ec83ee3
add SASL EXTERNAL authentication
4 files changed, 44 insertions(+), 8 deletions(-)

M src/components/ircv3.h
M src/components/server.c
M src/handlers/ircv3.c
M src/rirc.c
M src/components/ircv3.h => src/components/ircv3.h +1 -0
@@ 48,6 48,7 @@ struct ircv3_sasl
{
	enum {
		IRCV3_SASL_METHOD_NONE,
		IRCV3_SASL_METHOD_EXTERNAL,
		IRCV3_SASL_METHOD_PLAIN,
	} method;
	enum {

M src/components/server.c => src/components/server.c +8 -3
@@ 328,11 328,16 @@ server_set_005(struct server *s, char *str)
void
server_set_sasl(struct server *s, const char *method, const char *user, const char *pass)
{
	if (!strcasecmp(method, "PLAIN")) {
	free((void *)s->ircv3_sasl.user);
	free((void *)s->ircv3_sasl.pass);

		free((void *)s->ircv3_sasl.user);
		free((void *)s->ircv3_sasl.pass);
	if (!strcasecmp(method, "EXTERNAL")) {
		s->ircv3_sasl.method = IRCV3_SASL_METHOD_EXTERNAL;
		s->ircv3_sasl.user = NULL;
		s->ircv3_sasl.pass = NULL;
	}

	if (!strcasecmp(method, "PLAIN")) {
		s->ircv3_sasl.method = IRCV3_SASL_METHOD_PLAIN;
		s->ircv3_sasl.user = (user ? strdup(user) : NULL);
		s->ircv3_sasl.pass = (pass ? strdup(pass) : NULL);

M src/handlers/ircv3.c => src/handlers/ircv3.c +27 -1
@@ 36,6 36,7 @@ static int ircv3_cap_req_send(struct ircv3_caps*, struct server*);
static int ircv3_registered(struct server*);
static int ircv3_sasl_init(struct server*);

static int ircv3_recv_AUTHENTICATE_EXTERNAL(struct server*, struct irc_message*);
static int ircv3_recv_AUTHENTICATE_PLAIN(struct server*, struct irc_message*);

int


@@ 44,6 45,9 @@ ircv3_recv_AUTHENTICATE(struct server *s, struct irc_message *m)
	if (s->ircv3_sasl.method == IRCV3_SASL_METHOD_NONE)
		failf(s, "AUTHENTICATE: no SASL method");

	if (s->ircv3_sasl.method == IRCV3_SASL_METHOD_EXTERNAL)
		return (ircv3_recv_AUTHENTICATE_EXTERNAL(s, m));

	if (s->ircv3_sasl.method == IRCV3_SASL_METHOD_PLAIN)
		return (ircv3_recv_AUTHENTICATE_PLAIN(s, m));



@@ 571,6 575,25 @@ ircv3_recv_cap_NEW(struct server *s, struct irc_message *m)
}

static int
ircv3_recv_AUTHENTICATE_EXTERNAL(struct server *s, struct irc_message *m)
{
	/* C: AUTHENTICATE EXTERNAL
	 * S: +
	 * C: +
	 */

	if (s->ircv3_sasl.state != IRCV3_SASL_STATE_REQ_METHOD)
		failf(s, "Invalid SASL state for method EXTERNAL: %d", s->ircv3_sasl.state);

	if (strcmp(m->params, "+"))
		failf(s, "Invalid SASL response for method EXTERNAL: '%s'", m->params);

	sendf(s, "AUTHENTICATE +");

	return 0;
}

static int
ircv3_recv_AUTHENTICATE_PLAIN(struct server *s, struct irc_message *m)
{
	/* C: AUTHENTICATE PLAIN


@@ 593,7 616,7 @@ ircv3_recv_AUTHENTICATE_PLAIN(struct server *s, struct irc_message *m)
		failf(s, "Invalid SASL state for method PLAIN: %d", s->ircv3_sasl.state);

	if (strcmp(m->params, "+"))
		failf(s, "Invalid SASL response '%s'", m->params);
		failf(s, "Invalid SASL response for method PLAIN: '%s'", m->params);

	len = snprintf((char *)resp_dec, sizeof(resp_dec), "%s%c%s%c%s",
		s->ircv3_sasl.user, 0,


@@ 689,6 712,9 @@ ircv3_sasl_init(struct server *s)
	}

	switch (s->ircv3_sasl.method) {
		case IRCV3_SASL_METHOD_EXTERNAL:
			sendf(s, "AUTHENTICATE EXTERNAL");
			break;
		case IRCV3_SASL_METHOD_PLAIN:
			sendf(s, "AUTHENTICATE PLAIN");
			break;

M src/rirc.c => src/rirc.c +8 -4
@@ 312,15 312,15 @@ rirc_parse_args(int argc, char **argv)

			case '6': /* Set server TLS peer certificate verification mode */
				CHECK_SERVER_OPTARG(opt_c, 1);
				if (!strcmp(optarg, "0") || !strcasecmp(optarg, "disabled")) {
				if (!strcmp(optarg, "0") || !strcasecmp(optarg, "DISABLED")) {
					cli_servers[n_servers -1].tls_vrfy = IO_TLS_VRFY_DISABLED;
					break;
				}
				if (!strcmp(optarg, "1") || !strcasecmp(optarg, "optional")) {
				if (!strcmp(optarg, "1") || !strcasecmp(optarg, "OPTIONAL")) {
					cli_servers[n_servers -1].tls_vrfy = IO_TLS_VRFY_OPTIONAL;
					break;
				}
				if (!strcmp(optarg, "2") || !strcasecmp(optarg, "required")) {
				if (!strcmp(optarg, "2") || !strcasecmp(optarg, "REQUIRED")) {
					cli_servers[n_servers -1].tls_vrfy = IO_TLS_VRFY_REQUIRED;
					break;
				}


@@ 329,7 329,11 @@ rirc_parse_args(int argc, char **argv)

			case '7': /* Authenticate with SASL method */
				CHECK_SERVER_OPTARG(opt_c, 1);
				if (!strcasecmp(optarg, "plain")) {
				if (!strcasecmp(optarg, "EXTERNAL")) {
					cli_servers[n_servers - 1].sasl = optarg;
					break;
				}
				if (!strcasecmp(optarg, "PLAIN")) {
					cli_servers[n_servers - 1].sasl = optarg;
					break;
				}