mirror of
https://github.com/osmarks/ngircd.git
synced 2025-02-10 14:20:03 +00:00
Merge remote-tracking branch 'fgsch/certfp'
* fgsch/certfp: Simplify MOTD handling Add certificate fingerprint support
This commit is contained in:
commit
69ce65bacb
@ -228,6 +228,7 @@ The following <key> names are defined:
|
|||||||
- "cloakhost": the cloaked hostname of a client
|
- "cloakhost": the cloaked hostname of a client
|
||||||
- "info": info text ("real name") of a client
|
- "info": info text ("real name") of a client
|
||||||
- "user": the user name of a client (can't be empty)
|
- "user": the user name of a client (can't be empty)
|
||||||
|
- "certfp": the cert fingerprint of a client
|
||||||
|
|
||||||
|
|
||||||
III. Numerics used by IRC+ Protocol
|
III. Numerics used by IRC+ Protocol
|
||||||
|
@ -37,6 +37,7 @@ struct ConnSSL_State {
|
|||||||
void *cookie; /* pointer to server configuration structure
|
void *cookie; /* pointer to server configuration structure
|
||||||
(for outgoing connections), or NULL. */
|
(for outgoing connections), or NULL. */
|
||||||
#endif
|
#endif
|
||||||
|
char *fingerprint;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,11 +54,15 @@ static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c ));
|
|||||||
#define DH_BITS 2048
|
#define DH_BITS 2048
|
||||||
#define DH_BITS_MIN 1024
|
#define DH_BITS_MIN 1024
|
||||||
|
|
||||||
|
#define MAX_HASH_SIZE 64 /* from gnutls-int.h */
|
||||||
|
|
||||||
static gnutls_certificate_credentials_t x509_cred;
|
static gnutls_certificate_credentials_t x509_cred;
|
||||||
static gnutls_dh_params_t dh_params;
|
static gnutls_dh_params_t dh_params;
|
||||||
static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
|
static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CERTFP_LEN (20 * 2 + 1)
|
||||||
|
|
||||||
static bool ConnSSL_Init_SSL PARAMS(( CONNECTION *c ));
|
static bool ConnSSL_Init_SSL PARAMS(( CONNECTION *c ));
|
||||||
static int ConnectAccept PARAMS(( CONNECTION *c, bool connect ));
|
static int ConnectAccept PARAMS(( CONNECTION *c, bool connect ));
|
||||||
static int ConnSSL_HandleError PARAMS(( CONNECTION *c, const int code, const char *fname ));
|
static int ConnSSL_HandleError PARAMS(( CONNECTION *c, const int code, const char *fname ));
|
||||||
@ -145,6 +149,13 @@ pem_passwd_cb(char *buf, int size, int rwflag, void *password)
|
|||||||
memcpy(buf, (char *)(array_start(pass)), size);
|
memcpy(buf, (char *)(array_start(pass)), size);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
Verify_openssl(UNUSED int preverify_ok, UNUSED X509_STORE_CTX *x509_ctx)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -223,6 +234,10 @@ void ConnSSL_Free(CONNECTION *c)
|
|||||||
SSL_shutdown(ssl);
|
SSL_shutdown(ssl);
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
c->ssl_state.ssl = NULL;
|
c->ssl_state.ssl = NULL;
|
||||||
|
if (c->ssl_state.fingerprint) {
|
||||||
|
free(c->ssl_state.fingerprint);
|
||||||
|
c->ssl_state.fingerprint = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBGNUTLS
|
#ifdef HAVE_LIBGNUTLS
|
||||||
@ -277,6 +292,7 @@ ConnSSL_InitLibrary( void )
|
|||||||
|
|
||||||
SSL_CTX_set_options(newctx, SSL_OP_SINGLE_DH_USE|SSL_OP_NO_SSLv2);
|
SSL_CTX_set_options(newctx, SSL_OP_SINGLE_DH_USE|SSL_OP_NO_SSLv2);
|
||||||
SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||||
|
SSL_CTX_set_verify(newctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, Verify_openssl);
|
||||||
SSL_CTX_free(ssl_ctx);
|
SSL_CTX_free(ssl_ctx);
|
||||||
ssl_ctx = newctx;
|
ssl_ctx = newctx;
|
||||||
Log(LOG_INFO, "%s initialized.", SSLeay_version(SSLEAY_VERSION));
|
Log(LOG_INFO, "%s initialized.", SSLeay_version(SSLEAY_VERSION));
|
||||||
@ -404,6 +420,7 @@ ConnSSL_Init_SSL(CONNECTION *c)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
assert(c->ssl_state.ssl == NULL);
|
assert(c->ssl_state.ssl == NULL);
|
||||||
|
assert(c->ssl_state.fingerprint == NULL);
|
||||||
|
|
||||||
c->ssl_state.ssl = SSL_new(ssl_ctx);
|
c->ssl_state.ssl = SSL_new(ssl_ctx);
|
||||||
if (!c->ssl_state.ssl) {
|
if (!c->ssl_state.ssl) {
|
||||||
@ -432,6 +449,7 @@ ConnSSL_Init_SSL(CONNECTION *c)
|
|||||||
* http://www.mail-archive.com/help-gnutls@gnu.org/msg00286.html
|
* http://www.mail-archive.com/help-gnutls@gnu.org/msg00286.html
|
||||||
*/
|
*/
|
||||||
gnutls_transport_set_ptr(c->ssl_state.gnutls_session, (gnutls_transport_ptr_t) (long) c->sock);
|
gnutls_transport_set_ptr(c->ssl_state.gnutls_session, (gnutls_transport_ptr_t) (long) c->sock);
|
||||||
|
gnutls_certificate_server_set_request(c->ssl_state.gnutls_session, GNUTLS_CERT_REQUEST);
|
||||||
ret = gnutls_credentials_set(c->ssl_state.gnutls_session, GNUTLS_CRD_CERTIFICATE, x509_cred);
|
ret = gnutls_credentials_set(c->ssl_state.gnutls_session, GNUTLS_CRD_CERTIFICATE, x509_cred);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
Log(LOG_ERR, "gnutls_credentials_set: %s", gnutls_strerror(ret));
|
Log(LOG_ERR, "gnutls_credentials_set: %s", gnutls_strerror(ret));
|
||||||
@ -614,6 +632,77 @@ ConnSSL_Connect( CONNECTION *c )
|
|||||||
return ConnectAccept(c, true);
|
return ConnectAccept(c, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ConnSSL_InitFingerprint( CONNECTION *c )
|
||||||
|
{
|
||||||
|
const char hex[] = "0123456789abcdef";
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSSL
|
||||||
|
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||||
|
unsigned int digest_size;
|
||||||
|
X509 *cert;
|
||||||
|
|
||||||
|
cert = SSL_get_peer_certificate(c->ssl_state.ssl);
|
||||||
|
if (!cert)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!X509_digest(cert, EVP_sha1(), digest, &digest_size)) {
|
||||||
|
X509_free(cert);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_free(cert);
|
||||||
|
#endif /* HAVE_LIBSSL */
|
||||||
|
#ifdef HAVE_LIBGNUTLS
|
||||||
|
gnutls_x509_crt_t cert;
|
||||||
|
unsigned int cert_list_size;
|
||||||
|
const gnutls_datum_t *cert_list;
|
||||||
|
unsigned char digest[MAX_HASH_SIZE];
|
||||||
|
size_t digest_size;
|
||||||
|
|
||||||
|
if (gnutls_certificate_type_get(c->ssl_state.gnutls_session) != GNUTLS_CRT_X509)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cert_list_size = 0;
|
||||||
|
cert_list = gnutls_certificate_get_peers(c->ssl_state.gnutls_session,
|
||||||
|
&cert_list_size);
|
||||||
|
if (!cert_list) {
|
||||||
|
gnutls_x509_crt_deinit(cert);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
|
||||||
|
gnutls_x509_crt_deinit(cert);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
digest_size = sizeof(digest);
|
||||||
|
if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, digest, &digest_size)) {
|
||||||
|
gnutls_x509_crt_deinit(cert);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_x509_crt_deinit(cert);
|
||||||
|
#endif /* HAVE_LIBGNUTLS */
|
||||||
|
|
||||||
|
assert(c->ssl_state.fingerprint == NULL);
|
||||||
|
|
||||||
|
c->ssl_state.fingerprint = malloc(CERTFP_LEN);
|
||||||
|
if (!c->ssl_state.fingerprint)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < (int)digest_size; i++) {
|
||||||
|
c->ssl_state.fingerprint[i * 2] = hex[digest[i] / 16];
|
||||||
|
c->ssl_state.fingerprint[i * 2 + 1] = hex[digest[i] % 16];
|
||||||
|
}
|
||||||
|
c->ssl_state.fingerprint[i * 2] = '\0';
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* accept/connect wrapper. if connect is true, connect to peer, otherwise wait for incoming connection */
|
/* accept/connect wrapper. if connect is true, connect to peer, otherwise wait for incoming connection */
|
||||||
static int
|
static int
|
||||||
@ -634,6 +723,8 @@ ConnectAccept( CONNECTION *c, bool connect)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ConnSSL_HandleError(c, ret, "gnutls_handshake");
|
return ConnSSL_HandleError(c, ret, "gnutls_handshake");
|
||||||
#endif /* _GNUTLS */
|
#endif /* _GNUTLS */
|
||||||
|
(void)ConnSSL_InitFingerprint(c);
|
||||||
|
|
||||||
Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
|
Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
|
||||||
ConnSSL_LogCertInfo(c);
|
ConnSSL_LogCertInfo(c);
|
||||||
|
|
||||||
@ -725,6 +816,19 @@ ConnSSL_GetCipherInfo(CONNECTION *c, char *buf, size_t len)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
ConnSSL_GetFingerprint(CONNECTION *c)
|
||||||
|
{
|
||||||
|
return c->ssl_state.fingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ConnSSL_SetFingerprint(CONNECTION *c, const char *fingerprint)
|
||||||
|
{
|
||||||
|
assert (c != NULL);
|
||||||
|
c->ssl_state.fingerprint = strdup(fingerprint);
|
||||||
|
return c->ssl_state.fingerprint != NULL;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -26,6 +26,9 @@ GLOBAL ssize_t ConnSSL_Write PARAMS(( CONNECTION *c, const void *buf, size_t cou
|
|||||||
GLOBAL ssize_t ConnSSL_Read PARAMS(( CONNECTION *c, void *buf, size_t count));
|
GLOBAL ssize_t ConnSSL_Read PARAMS(( CONNECTION *c, void *buf, size_t count));
|
||||||
|
|
||||||
GLOBAL bool ConnSSL_GetCipherInfo PARAMS(( CONNECTION *c, char *buf, size_t len ));
|
GLOBAL bool ConnSSL_GetCipherInfo PARAMS(( CONNECTION *c, char *buf, size_t len ));
|
||||||
|
GLOBAL char *ConnSSL_GetFingerprint PARAMS(( CONNECTION *c ));
|
||||||
|
GLOBAL bool ConnSSL_SetFingerprint PARAMS(( CONNECTION *c, const char *fingerprint ));
|
||||||
|
|
||||||
#endif /* SSL_SUPPORT */
|
#endif /* SSL_SUPPORT */
|
||||||
#endif /* conn_ssl_h */
|
#endif /* conn_ssl_h */
|
||||||
|
|
||||||
|
@ -2611,6 +2611,45 @@ Conn_UsesSSL(CONN_ID Idx)
|
|||||||
return Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL);
|
return Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL char *
|
||||||
|
Conn_GetFingerprint(CONN_ID Idx)
|
||||||
|
{
|
||||||
|
if (Idx < 0)
|
||||||
|
return NULL;
|
||||||
|
assert(Idx < (int) array_length(&My_ConnArray, sizeof(CONNECTION)));
|
||||||
|
return ConnSSL_GetFingerprint(&My_Connections[Idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL bool
|
||||||
|
Conn_SetFingerprint(CONN_ID Idx, const char *fingerprint)
|
||||||
|
{
|
||||||
|
if (Idx < 0)
|
||||||
|
return false;
|
||||||
|
assert(Idx < (int) array_length(&My_ConnArray, sizeof(CONNECTION)));
|
||||||
|
return ConnSSL_SetFingerprint(&My_Connections[Idx], fingerprint);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
GLOBAL bool
|
||||||
|
Conn_UsesSSL(UNUSED CONN_ID Idx)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL char *
|
||||||
|
Conn_GetFingerprint(UNUSED CONN_ID Idx)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL bool
|
||||||
|
Conn_SetFingerprint(UNUSED CONN_ID Idx, UNUSED const char *fingerprint)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -139,13 +139,12 @@ GLOBAL CONN_ID Conn_GetFromProc PARAMS((int fd));
|
|||||||
GLOBAL CLIENT* Conn_GetClient PARAMS((CONN_ID i));
|
GLOBAL CLIENT* Conn_GetClient PARAMS((CONN_ID i));
|
||||||
GLOBAL PROC_STAT* Conn_GetProcStat PARAMS((CONN_ID i));
|
GLOBAL PROC_STAT* Conn_GetProcStat PARAMS((CONN_ID i));
|
||||||
|
|
||||||
|
GLOBAL char *Conn_GetFingerprint PARAMS((CONN_ID Idx));
|
||||||
|
GLOBAL bool Conn_SetFingerprint PARAMS((CONN_ID Idx, const char *fingerprint));
|
||||||
|
GLOBAL bool Conn_UsesSSL PARAMS((CONN_ID Idx));
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
GLOBAL bool Conn_GetCipherInfo PARAMS((CONN_ID Idx, char *buf, size_t len));
|
GLOBAL bool Conn_GetCipherInfo PARAMS((CONN_ID Idx, char *buf, size_t len));
|
||||||
GLOBAL bool Conn_UsesSSL PARAMS((CONN_ID Idx));
|
|
||||||
#else
|
|
||||||
static inline bool
|
|
||||||
Conn_UsesSSL(UNUSED CONN_ID Idx)
|
|
||||||
{ return false; }
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GLOBAL const char *Conn_GetIPAInfo PARAMS((CONN_ID Idx));
|
GLOBAL const char *Conn_GetIPAInfo PARAMS((CONN_ID Idx));
|
||||||
|
@ -381,11 +381,20 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
|
|||||||
return DISCONNECTED;
|
return DISCONNECTED;
|
||||||
|
|
||||||
/* Connected using SSL? */
|
/* Connected using SSL? */
|
||||||
if (Conn_UsesSSL(Client_Conn(c)) &&
|
if (Conn_UsesSSL(Client_Conn(c))) {
|
||||||
!IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from),
|
if (!IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from),
|
||||||
Client_ID(c)))
|
Client_ID(c)))
|
||||||
return DISCONNECTED;
|
return DISCONNECTED;
|
||||||
|
|
||||||
|
/* Certificate fingerprint? */
|
||||||
|
if (Conn_GetFingerprint(Client_Conn(c)) &&
|
||||||
|
from == c &&
|
||||||
|
!IRC_WriteStrClient(from, RPL_WHOISCERTFP_MSG,
|
||||||
|
Client_ID(from), Client_ID(c),
|
||||||
|
Conn_GetFingerprint(Client_Conn(c))))
|
||||||
|
return DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
/* Registered nickname? */
|
/* Registered nickname? */
|
||||||
if (Client_HasMode(c, 'R') &&
|
if (Client_HasMode(c, 'R') &&
|
||||||
!IRC_WriteStrClient(from, RPL_WHOISREGNICK_MSG,
|
!IRC_WriteStrClient(from, RPL_WHOISREGNICK_MSG,
|
||||||
@ -439,51 +448,37 @@ WHOWAS_EntryWrite(CLIENT *prefix, WHOWAS *entry)
|
|||||||
entry->id, entry->server, t_str);
|
entry->id, entry->server, t_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
Show_MOTD_Start(CLIENT *Client)
|
|
||||||
{
|
|
||||||
return IRC_WriteStrClient(Client, RPL_MOTDSTART_MSG,
|
|
||||||
Client_ID( Client ), Client_ID( Client_ThisServer( )));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
Show_MOTD_Sendline(CLIENT *Client, const char *msg)
|
|
||||||
{
|
|
||||||
return IRC_WriteStrClient(Client, RPL_MOTD_MSG, Client_ID( Client ), msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
Show_MOTD_End(CLIENT *Client)
|
|
||||||
{
|
|
||||||
if (!IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, Client_ID(Client)))
|
|
||||||
return DISCONNECTED;
|
|
||||||
|
|
||||||
if (*Conf_CloakHost)
|
|
||||||
return IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG,
|
|
||||||
Client_ID(Client),
|
|
||||||
Client_Hostname(Client));
|
|
||||||
|
|
||||||
return CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
static bool Show_MOTD_SSLInfo(CLIENT *Client)
|
static bool
|
||||||
|
Show_MOTD_SSLInfo(CLIENT *Client)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
char buf[COMMAND_LEN];
|
||||||
char buf[COMMAND_LEN] = "Connected using Cipher ";
|
char c_str[128];
|
||||||
|
|
||||||
|
if (Conn_GetCipherInfo(Client_Conn(Client), c_str, sizeof(c_str))) {
|
||||||
|
snprintf(buf, sizeof(buf), "Connected using Cipher %s", c_str);
|
||||||
|
if (!IRC_WriteStrClient(Client, RPL_MOTD_MSG,
|
||||||
|
Client_ID(Client), buf))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Conn_GetFingerprint(Client_Conn(Client))) {
|
||||||
|
snprintf(buf, sizeof(buf),
|
||||||
|
"Your client certificate fingerprint is: %s",
|
||||||
|
Conn_GetFingerprint(Client_Conn(Client)));
|
||||||
|
if (!IRC_WriteStrClient(Client, RPL_MOTD_MSG,
|
||||||
|
Client_ID(Client), buf))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Conn_GetCipherInfo(Client_Conn(Client), buf + 23, sizeof buf - 23))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!Show_MOTD_Sendline(Client, buf))
|
|
||||||
ret = false;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline bool
|
static bool
|
||||||
Show_MOTD_SSLInfo(UNUSED CLIENT *c)
|
Show_MOTD_SSLInfo(UNUSED CLIENT *c)
|
||||||
{ return true; }
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Global functions */
|
/* Global functions */
|
||||||
@ -1477,7 +1472,8 @@ IRC_Show_MOTD( CLIENT *Client )
|
|||||||
if (len_tot == 0 && !Conn_UsesSSL(Client_Conn(Client)))
|
if (len_tot == 0 && !Conn_UsesSSL(Client_Conn(Client)))
|
||||||
return IRC_WriteStrClient(Client, ERR_NOMOTD_MSG, Client_ID(Client));
|
return IRC_WriteStrClient(Client, ERR_NOMOTD_MSG, Client_ID(Client));
|
||||||
|
|
||||||
if (!Show_MOTD_Start(Client))
|
if (!IRC_WriteStrClient(Client, RPL_MOTDSTART_MSG, Client_ID(Client),
|
||||||
|
Client_ID(Client_ThisServer())))
|
||||||
return DISCONNECTED;
|
return DISCONNECTED;
|
||||||
|
|
||||||
line = array_start(&Conf_Motd);
|
line = array_start(&Conf_Motd);
|
||||||
@ -1487,14 +1483,23 @@ IRC_Show_MOTD( CLIENT *Client )
|
|||||||
assert(len_tot >= len_str);
|
assert(len_tot >= len_str);
|
||||||
len_tot -= len_str;
|
len_tot -= len_str;
|
||||||
|
|
||||||
if (!Show_MOTD_Sendline(Client, line))
|
if (!IRC_WriteStrClient(Client, RPL_MOTD_MSG, Client_ID(Client), line))
|
||||||
return DISCONNECTED;
|
return DISCONNECTED;
|
||||||
line += len_str;
|
line += len_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Show_MOTD_SSLInfo(Client))
|
if (!Show_MOTD_SSLInfo(Client))
|
||||||
return DISCONNECTED;
|
return DISCONNECTED;
|
||||||
return Show_MOTD_End(Client);
|
|
||||||
|
if (!IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, Client_ID(Client)))
|
||||||
|
return DISCONNECTED;
|
||||||
|
|
||||||
|
if (*Conf_CloakHost)
|
||||||
|
return IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG,
|
||||||
|
Client_ID(Client),
|
||||||
|
Client_Hostname(Client));
|
||||||
|
|
||||||
|
return CONNECTED;
|
||||||
} /* IRC_Show_MOTD */
|
} /* IRC_Show_MOTD */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,6 +96,8 @@ IRC_METADATA(CLIENT *Client, REQUEST *Req)
|
|||||||
Client_SetInfo(target, Req->argv[2]);
|
Client_SetInfo(target, Req->argv[2]);
|
||||||
else if (*Req->argv[2] && strcasecmp(Req->argv[1], "user") == 0)
|
else if (*Req->argv[2] && strcasecmp(Req->argv[1], "user") == 0)
|
||||||
Client_SetUser(target, Req->argv[2], true);
|
Client_SetUser(target, Req->argv[2], true);
|
||||||
|
else if (*Req->argv[2] && strcasecmp(Req->argv[1], "certfp") == 0)
|
||||||
|
Conn_SetFingerprint(Client_Conn(target), Req->argv[2]);
|
||||||
else
|
else
|
||||||
Log(LOG_WARNING,
|
Log(LOG_WARNING,
|
||||||
"Ignored metadata update from \"%s\" for client \"%s\": \"%s=%s\" - unknown key!",
|
"Ignored metadata update from \"%s\" for client \"%s\": \"%s=%s\" - unknown key!",
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#define RPL_NETUSERS_MSG "266 %s %lu %lu :Current global users: %lu, Max: %lu"
|
#define RPL_NETUSERS_MSG "266 %s %lu %lu :Current global users: %lu, Max: %lu"
|
||||||
#define RPL_STATSCONN_MSG "250 %s :Highest connection count: %lu (%lu connections received)"
|
#define RPL_STATSCONN_MSG "250 %s :Highest connection count: %lu (%lu connections received)"
|
||||||
#define RPL_WHOISSSL_MSG "275 %s %s :is connected via SSL (secure link)"
|
#define RPL_WHOISSSL_MSG "275 %s %s :is connected via SSL (secure link)"
|
||||||
|
#define RPL_WHOISCERTFP_MSG "276 %s %s :has client certificate fingerprint %s"
|
||||||
|
|
||||||
#define RPL_AWAY_MSG "301 %s %s :%s"
|
#define RPL_AWAY_MSG "301 %s %s :%s"
|
||||||
#define RPL_USERHOST_MSG "302 %s :"
|
#define RPL_USERHOST_MSG "302 %s :"
|
||||||
|
@ -212,6 +212,14 @@ Announce_User(CLIENT * Client, CLIENT * User)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Conn_GetFingerprint(conn)) {
|
||||||
|
if (!IRC_WriteStrClient(Client,
|
||||||
|
"METADATA %s certfp :%s",
|
||||||
|
Client_ID(User),
|
||||||
|
Conn_GetFingerprint(conn)))
|
||||||
|
return DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
return CONNECTED;
|
return CONNECTED;
|
||||||
} /* Announce_User */
|
} /* Announce_User */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user