diff --git a/include/client.h b/include/client.h index 508b9db..8af1709 100644 --- a/include/client.h +++ b/include/client.h @@ -161,6 +161,7 @@ struct Client struct PreClient *preClient; time_t large_ctcp_sent; /* ctcp to large group sent, relax flood checks */ + char *certfp; /* client certificate fingerprint */ }; struct LocalUser diff --git a/include/numeric.h b/include/numeric.h index 6b449e4..92dc560 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -120,6 +120,8 @@ extern const char *form_str(int); #define RPL_PRIVS 270 /* from ircu */ +#define RPL_WHOISCERTFP 276 /* from oftc-hybrid */ + #define RPL_ACCEPTLIST 281 #define RPL_ENDOFACCEPT 282 diff --git a/modules/Makefile.in b/modules/Makefile.in index f1807cf..dd96664 100644 --- a/modules/Makefile.in +++ b/modules/Makefile.in @@ -55,6 +55,7 @@ TSRCS = \ m_away.c \ m_cap.c \ m_capab.c \ + m_certfp.c \ m_challenge.c \ m_chghost.c \ m_close.c \ diff --git a/modules/m_certfp.c b/modules/m_certfp.c new file mode 100644 index 0000000..6670f88 --- /dev/null +++ b/modules/m_certfp.c @@ -0,0 +1,69 @@ +/* + * m_certfp.c: propagates client certificate fingerprint information + * + * Copyright (C) 2010 Jilles Tjoelker + * Copyright (C) 2010 charybdis development team + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1.Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2.Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "client.h" +#include "common.h" +#include "match.h" +#include "hash.h" +#include "ircd.h" +#include "numeric.h" +#include "send.h" +#include "msg.h" +#include "modules.h" + +static int me_certfp(struct Client *, struct Client *, int, const char **); + +struct Message certfp_msgtab = { + "CERTFP", 0, 0, 0, MFLG_SLOW, + {mg_unreg, mg_ignore, mg_ignore, mg_ignore, {me_certfp, 0}, mg_ignore} +}; + +mapi_clist_av1 certfp_clist[] = { &certfp_msgtab, NULL }; + +DECLARE_MODULE_AV1(certfp, NULL, NULL, certfp_clist, NULL, NULL, "$Revision$"); + +/* +** me_certfp +** parv[1] = certfp string +*/ +static int +me_certfp(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +{ + if (!IsPerson(source_p)) + return 0; + if (parc != 2) + return 0; + + rb_free(source_p->certfp); + source_p->certfp = NULL; + if (!EmptyString(parv[1])) + source_p->certfp = rb_strdup(parv[1]); + return 0; +} diff --git a/modules/m_whois.c b/modules/m_whois.c index ca8dc23..f4fb885 100644 --- a/modules/m_whois.c +++ b/modules/m_whois.c @@ -320,6 +320,11 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) if(IsSSLClient(target_p)) sendto_one_numeric(source_p, RPL_WHOISSECURE, form_str(RPL_WHOISSECURE), target_p->name); + if((source_p == target_p || IsOper(source_p)) && + target_p->certfp != NULL) + sendto_one_numeric(source_p, RPL_WHOISCERTFP, + form_str(RPL_WHOISCERTFP), + target_p->name, target_p->certfp); if(MyClient(target_p)) { diff --git a/src/client.c b/src/client.c index 428b799..b3f33c3 100644 --- a/src/client.c +++ b/src/client.c @@ -256,6 +256,7 @@ free_client(struct Client *client_p) s_assert(&me != client_p); free_local_client(client_p); free_pre_client(client_p); + rb_free(client_p->certfp); rb_bh_free(client_heap, client_p); } diff --git a/src/messages.tab b/src/messages.tab index 2602cb6..af5ebab 100644 --- a/src/messages.tab +++ b/src/messages.tab @@ -297,7 +297,7 @@ static const char * replies[] = { /* 273 */ NULL, /* 274 */ NULL, /* 275 */ NULL, -/* 276 */ NULL, +/* 276 RPL_WHOISCERTFP */ "%s :has client certificate fingerprint %s", /* 277 */ NULL, /* 278 */ NULL, /* 279 */ NULL, diff --git a/src/s_serv.c b/src/s_serv.c index 10c0fab..a43c60c 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -506,6 +506,10 @@ burst_TS6(struct Client *client_p) IsIPSpoof(target_p) ? "0" : target_p->sockhost, target_p->id, target_p->info); + if(!EmptyString(target_p->certfp)) + sendto_one(client_p, ":%s ENCAP * CERTFP :%s", + use_id(target_p), target_p->certfp); + if(!IsCapable(client_p, CAP_EUID)) { if(IsDynSpoof(target_p)) diff --git a/src/s_user.c b/src/s_user.c index 7d7bc1b..b774e90 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -633,6 +633,11 @@ introduce_client(struct Client *client_p, struct Client *source_p, struct User * IsIPSpoof(source_p) ? "0" : sockhost, source_p->id, source_p->info); + if(!EmptyString(source_p->certfp)) + sendto_server(client_p, NULL, CAP_TS6, NOCAPS, + ":%s ENCAP * CERTFP :%s", + use_id(source_p), source_p->certfp); + if (IsDynSpoof(source_p)) { sendto_server(client_p, NULL, CAP_TS6, use_euid ? CAP_EUID : NOCAPS, ":%s ENCAP * REALHOST %s", diff --git a/src/sslproc.c b/src/sslproc.c index a886b66..178fde3 100644 --- a/src/sslproc.c +++ b/src/sslproc.c @@ -408,7 +408,7 @@ ssl_process_certfp(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) struct Client *client_p; int32_t fd; uint8_t *certfp; - char certfp_string[RB_SSL_CERTFP_LEN * 2 + 1]; + char *certfp_string; int i; if(ctl_buf->buflen != 5 + RB_SSL_CERTFP_LEN) @@ -419,10 +419,12 @@ ssl_process_certfp(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) client_p = find_cli_fd_hash(fd); if(client_p == NULL) return; + rb_free(client_p->certfp); + certfp_string = rb_malloc(RB_SSL_CERTFP_LEN * 2 + 1); for(i = 0; i < RB_SSL_CERTFP_LEN; i++) rb_snprintf(certfp_string + 2 * i, 3, "%02x", certfp[i]); - sendto_one_notice(client_p, ":*** Your client certificate fingerprint is: %s", certfp_string); + client_p->certfp = certfp_string; } static void