unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

starttls.c (3062B)

      1 /*
      2  *   IRC - Internet Relay Chat, src/modules/starttls.c
      3  *   (C) 2009 Syzop & The UnrealIRCd Team
      4  *
      5  *   See file AUTHORS in IRC package for additional names of
      6  *   the programmers.
      7  *
      8  *   This program is free software; you can redistribute it and/or modify
      9  *   it under the terms of the GNU General Public License as published by
     10  *   the Free Software Foundation; either version 1, or (at your option)
     11  *   any later version.
     12  *
     13  *   This program is distributed in the hope that it will be useful,
     14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *   GNU General Public License for more details.
     17  *
     18  *   You should have received a copy of the GNU General Public License
     19  *   along with this program; if not, write to the Free Software
     20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     21  */
     22 
     23 #include "unrealircd.h"
     24 
     25 CMD_FUNC(cmd_starttls);
     26 
     27 #define MSG_STARTTLS 	"STARTTLS"	
     28 
     29 ModuleHeader MOD_HEADER
     30   = {
     31 	"starttls",
     32 	"5.0",
     33 	"command /starttls", 
     34 	"UnrealIRCd Team",
     35 	"unrealircd-6",
     36     };
     37 
     38 long CLICAP_STARTTLS;
     39 
     40 MOD_INIT()
     41 {
     42 	ClientCapabilityInfo cap;
     43 	
     44 	MARK_AS_OFFICIAL_MODULE(modinfo);
     45 	CommandAdd(modinfo->handle, MSG_STARTTLS, cmd_starttls, MAXPARA, CMD_UNREGISTERED);
     46 	memset(&cap, 0, sizeof(cap));
     47 	cap.name = "tls";
     48 	ClientCapabilityAdd(modinfo->handle, &cap, &CLICAP_STARTTLS);
     49 
     50 	return MOD_SUCCESS;
     51 }
     52 
     53 MOD_LOAD()
     54 {
     55 	return MOD_SUCCESS;
     56 }
     57 
     58 MOD_UNLOAD()
     59 {
     60 	return MOD_SUCCESS;
     61 }
     62 
     63 CMD_FUNC(cmd_starttls)
     64 {
     65 	SSL_CTX *ctx;
     66 	int tls_options;
     67 
     68 	if (!MyConnect(client) || !IsUnknown(client))
     69 		return;
     70 
     71 	ctx = client->local->listener->ssl_ctx ? client->local->listener->ssl_ctx : ctx_server;
     72 	tls_options = client->local->listener->tls_options ? client->local->listener->tls_options->options : iConf.tls_options->options;
     73 
     74 	/* This should never happen? */
     75 	if (!ctx)
     76 	{
     77 		/* Pretend STARTTLS is an unknown command, this is the safest approach */
     78 		sendnumeric(client, ERR_NOTREGISTERED);
     79 		return;
     80 	}
     81 
     82 	/* Is STARTTLS disabled? (same response as above) */
     83 	if (tls_options & TLSFLAG_NOSTARTTLS)
     84 	{
     85 		sendnumeric(client, ERR_NOTREGISTERED);
     86 		return;
     87 	}
     88 
     89 	if (IsSecure(client))
     90 	{
     91 		sendnumeric(client, ERR_STARTTLS, "STARTTLS failed. Already using TLS.");
     92 		return;
     93 	}
     94 
     95 	dbuf_delete(&client->local->recvQ, DBufLength(&client->local->recvQ)); /* Clear up any remaining plaintext commands */
     96 	sendnumeric(client, RPL_STARTTLS);
     97 	send_queued(client);
     98 
     99 	SetStartTLSHandshake(client);
    100 	if ((client->local->ssl = SSL_new(ctx)) == NULL)
    101 		goto fail;
    102 	SetTLS(client);
    103 	SSL_set_fd(client->local->ssl, client->local->fd);
    104 	SSL_set_nonblocking(client->local->ssl);
    105 	if (!unreal_tls_accept(client, client->local->fd))
    106 	{
    107 		SSL_set_shutdown(client->local->ssl, SSL_RECEIVED_SHUTDOWN);
    108 		SSL_smart_shutdown(client->local->ssl);
    109 		SSL_free(client->local->ssl);
    110 		goto fail;
    111 	}
    112 
    113 	/* HANDSHAKE IN PROGRESS */
    114 	return;
    115 fail:
    116 	/* Failure */
    117 	sendnumeric(client, ERR_STARTTLS, "STARTTLS failed");
    118 	client->local->ssl = NULL;
    119 	ClearTLS(client);
    120 	SetUnknown(client);
    121 }