unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive |
certfp.c (3823B)
1 /* 2 * Certificate Fingerprint Module 3 * This grabs the SHA256 fingerprint of the TLS client certificate 4 * the user is using, shares it with the other servers (and rest of 5 * UnrealIRCd) and shows it in /WHOIS etc. 6 * 7 * (C) Copyright 2014-2015 The UnrealIRCd team (Syzop, DBoyz, Nath and others) 8 * 9 * License: GPLv2 or later 10 */ 11 12 #include "unrealircd.h" 13 14 ModuleHeader MOD_HEADER 15 = { 16 "certfp", 17 "5.0", 18 "Certificate fingerprint", 19 "UnrealIRCd Team", 20 "unrealircd-6", 21 }; 22 23 /* Forward declarations */ 24 void certfp_free(ModData *m); 25 const char *certfp_serialize(ModData *m); 26 void certfp_unserialize(const char *str, ModData *m); 27 int certfp_handshake(Client *client); 28 int certfp_connect(Client *client); 29 int certfp_whois(Client *client, Client *target, NameValuePrioList **list); 30 int certfp_json_expand_client(Client *client, int detail, json_t *j); 31 32 ModDataInfo *certfp_md; /* Module Data structure which we acquire */ 33 34 MOD_INIT() 35 { 36 ModDataInfo mreq; 37 38 MARK_AS_OFFICIAL_MODULE(modinfo); 39 40 memset(&mreq, 0, sizeof(mreq)); 41 mreq.name = "certfp"; 42 mreq.free = certfp_free; 43 mreq.serialize = certfp_serialize; 44 mreq.unserialize = certfp_unserialize; 45 mreq.sync = MODDATA_SYNC_EARLY; 46 mreq.type = MODDATATYPE_CLIENT; 47 certfp_md = ModDataAdd(modinfo->handle, mreq); 48 if (!certfp_md) 49 abort(); 50 51 HookAdd(modinfo->handle, HOOKTYPE_LOCAL_CONNECT, 0, certfp_connect); 52 HookAdd(modinfo->handle, HOOKTYPE_HANDSHAKE, 0, certfp_handshake); 53 HookAdd(modinfo->handle, HOOKTYPE_SERVER_HANDSHAKE_OUT, 0, certfp_handshake); 54 HookAdd(modinfo->handle, HOOKTYPE_WHOIS, 0, certfp_whois); 55 HookAdd(modinfo->handle, HOOKTYPE_JSON_EXPAND_CLIENT, 0, certfp_json_expand_client); 56 57 return MOD_SUCCESS; 58 } 59 60 MOD_LOAD() 61 { 62 return MOD_SUCCESS; 63 } 64 65 66 MOD_UNLOAD() 67 { 68 return MOD_SUCCESS; 69 } 70 71 /* 72 * Obtain client's fingerprint. 73 */ 74 char *get_fingerprint_for_client(Client *client) 75 { 76 unsigned int n; 77 unsigned int l; 78 unsigned char md[EVP_MAX_MD_SIZE]; 79 static char hex[EVP_MAX_MD_SIZE * 2 + 1]; 80 const EVP_MD *digest = EVP_sha256(); 81 X509 *x509_clientcert = NULL; 82 83 if (!MyConnect(client) || !client->local->ssl) 84 return NULL; 85 86 x509_clientcert = SSL_get_peer_certificate(client->local->ssl); 87 88 if (x509_clientcert) 89 { 90 if (X509_digest(x509_clientcert, digest, md, &n)) { 91 binarytohex(md, n, hex); 92 X509_free(x509_clientcert); 93 return hex; 94 } 95 X509_free(x509_clientcert); 96 } 97 return NULL; 98 } 99 100 int certfp_handshake(Client *client) 101 { 102 if (client->local->ssl) 103 { 104 char *fp = get_fingerprint_for_client(client); 105 106 if (!fp) 107 return 0; 108 109 moddata_client_set(client, "certfp", fp); /* set & broadcast */ 110 } 111 return 0; 112 } 113 114 int certfp_connect(Client *client) 115 { 116 if (IsSecure(client)) 117 { 118 const char *fp = moddata_client_get(client, "certfp"); 119 120 if (fp && !iConf.no_connect_tls_info) 121 sendnotice(client, "*** Your TLS certificate fingerprint is %s", fp); 122 } 123 124 return 0; 125 } 126 127 int certfp_whois(Client *client, Client *target, NameValuePrioList **list) 128 { 129 const char *fp = moddata_client_get(target, "certfp"); 130 char buf[512]; 131 132 if (!fp) 133 return 0; 134 135 if (whois_get_policy(client, target, "certfp") == WHOIS_CONFIG_DETAILS_FULL) 136 add_nvplist_numeric(list, 0, "certfp", client, RPL_WHOISCERTFP, target->name, fp); 137 138 return 0; 139 } 140 141 void certfp_free(ModData *m) 142 { 143 safe_free(m->str); 144 } 145 146 const char *certfp_serialize(ModData *m) 147 { 148 if (!m->str) 149 return NULL; 150 return m->str; 151 } 152 153 void certfp_unserialize(const char *str, ModData *m) 154 { 155 safe_strdup(m->str, str); 156 } 157 158 int certfp_json_expand_client(Client *client, int detail, json_t *j) 159 { 160 json_t *tls; 161 const char *str; 162 163 if (detail < 2) 164 return 0; 165 166 str = moddata_client_get(client, "certfp"); 167 if (!str) 168 return 0; 169 170 tls = json_object_get(j, "tls"); 171 if (!tls) 172 { 173 tls = json_object(); 174 json_object_set_new(j, "tls", tls); 175 } 176 177 json_object_set_new(tls, "certfp", json_string_unreal(str)); 178 179 return 0; 180 }