unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
certfp.c (3981B)
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 char hexchars[16] = "0123456789abcdef"; 81 const EVP_MD *digest = EVP_sha256(); 82 X509 *x509_clientcert = NULL; 83 84 if (!MyConnect(client) || !client->local->ssl) 85 return NULL; 86 87 x509_clientcert = SSL_get_peer_certificate(client->local->ssl); 88 89 if (x509_clientcert) 90 { 91 if (X509_digest(x509_clientcert, digest, md, &n)) { 92 int j = 0; 93 for (l=0; l<n; l++) { 94 hex[j++] = hexchars[(md[l] >> 4) & 0xF]; 95 hex[j++] = hexchars[md[l] & 0xF]; 96 } 97 hex[j] = '\0'; 98 X509_free(x509_clientcert); 99 return hex; 100 } 101 X509_free(x509_clientcert); 102 } 103 return NULL; 104 } 105 106 int certfp_handshake(Client *client) 107 { 108 if (client->local->ssl) 109 { 110 char *fp = get_fingerprint_for_client(client); 111 112 if (!fp) 113 return 0; 114 115 moddata_client_set(client, "certfp", fp); /* set & broadcast */ 116 } 117 return 0; 118 } 119 120 int certfp_connect(Client *client) 121 { 122 if (IsSecure(client)) 123 { 124 const char *fp = moddata_client_get(client, "certfp"); 125 126 if (fp && !iConf.no_connect_tls_info) 127 sendnotice(client, "*** Your TLS certificate fingerprint is %s", fp); 128 } 129 130 return 0; 131 } 132 133 int certfp_whois(Client *client, Client *target, NameValuePrioList **list) 134 { 135 const char *fp = moddata_client_get(target, "certfp"); 136 char buf[512]; 137 138 if (!fp) 139 return 0; 140 141 if (whois_get_policy(client, target, "certfp") == WHOIS_CONFIG_DETAILS_FULL) 142 add_nvplist_numeric(list, 0, "certfp", client, RPL_WHOISCERTFP, target->name, fp); 143 144 return 0; 145 } 146 147 void certfp_free(ModData *m) 148 { 149 safe_free(m->str); 150 } 151 152 const char *certfp_serialize(ModData *m) 153 { 154 if (!m->str) 155 return NULL; 156 return m->str; 157 } 158 159 void certfp_unserialize(const char *str, ModData *m) 160 { 161 safe_strdup(m->str, str); 162 } 163 164 int certfp_json_expand_client(Client *client, int detail, json_t *j) 165 { 166 json_t *tls; 167 const char *str; 168 169 if (detail < 2) 170 return 0; 171 172 str = moddata_client_get(client, "certfp"); 173 if (!str) 174 return 0; 175 176 tls = json_object_get(j, "tls"); 177 if (!tls) 178 { 179 tls = json_object(); 180 json_object_set_new(j, "tls", tls); 181 } 182 183 json_object_set_new(tls, "certfp", json_string_unreal(str)); 184 185 return 0; 186 }