@@ -213,6 +213,18 @@ static SSL_SESSION *cbtls_get_session(UNUSED SSL *s,
213213 return NULL ;
214214}
215215
216+ /*
217+ * For creating certificate attributes.
218+ */
219+ static const char * cert_attr_names [5 ][2 ] = {
220+ { "TLS-Client-Cert-Serial" , "TLS-Cert-Serial" },
221+ { "TLS-Client-Cert-Expiration" , "TLS-Cert-Expiraton" },
222+ { "TLS-Client-Cert-Issuer" , "TLS-Cert-Issuer" },
223+ { "TLS-Client-Cert-Subject" , "TLS-Cert-Subject" },
224+ { "TLS-Client-Cert-Common-Name" , "TLS-Cert-Common-Name" }
225+ };
226+
227+
216228/*
217229 * Before trusting a certificate, you must make sure that the
218230 * certificate is 'valid'. There are several steps that your
@@ -244,23 +256,23 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
244256 char issuer [1024 ]; /* Used for the issuer name */
245257 char common_name [1024 ];
246258 char cn_str [1024 ];
259+ char buf [64 ];
247260 EAP_HANDLER * handler = NULL ;
248261 X509 * client_cert ;
249262 SSL * ssl ;
250- int err , depth ;
263+ int err , depth , lookup ;
251264 EAP_TLS_CONF * conf ;
252265 int my_ok = ok ;
253266 REQUEST * request ;
267+ ASN1_INTEGER * sn = NULL ;
268+ ASN1_TIME * asn_time = NULL ;
254269
255270 client_cert = X509_STORE_CTX_get_current_cert (ctx );
256271 err = X509_STORE_CTX_get_error (ctx );
257272 depth = X509_STORE_CTX_get_error_depth (ctx );
258273
259- if (!my_ok ) {
260- radlog (L_ERR ,"--> verify error:num=%d:%s\n" ,err ,
261- X509_verify_cert_error_string (err ));
262- return my_ok ;
263- }
274+ lookup = depth ;
275+ if (lookup > 1 ) lookup = 1 ;
264276
265277 /*
266278 * Retrieve the pointer to the SSL of the connection currently treated
@@ -271,24 +283,74 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
271283 request = handler -> request ;
272284 conf = (EAP_TLS_CONF * )SSL_get_ex_data (ssl , 1 );
273285
286+ /*
287+ * Get the Serial Number
288+ */
289+ buf [0 ] = '\0' ;
290+ sn = X509_get_serialNumber (client_cert );
291+ if (sn && (sn -> length < (sizeof (buf ) / 2 ))) {
292+ char * p = buf ;
293+ int i ;
294+
295+ for (i = 0 ; i < sn -> length ; i ++ ) {
296+ sprintf (buf , "%02x" , (unsigned int )sn -> data [i ]);
297+ p += 2 ;
298+ }
299+ pairadd (& handler -> certs ,
300+ pairmake (cert_attr_names [0 ][lookup ], buf , T_OP_SET ));
301+ }
302+
303+
304+ /*
305+ * Get the Expiration Date
306+ */
307+ buf [0 ] = '\0' ;
308+ asn_time = X509_get_notAfter (client_cert );
309+ if (asn_time && (asn_time -> length < MAX_STRING_LEN )) {
310+ memcpy (buf , (char * ) asn_time -> data , asn_time -> length );
311+ buf [asn_time -> length ] = '\0' ;
312+ pairadd (& handler -> certs ,
313+ pairmake (cert_attr_names [1 ][lookup ], buf , T_OP_SET ));
314+ }
315+
274316 /*
275317 * Get the Subject & Issuer
276318 */
277319 subject [0 ] = issuer [0 ] = '\0' ;
278320 X509_NAME_oneline (X509_get_subject_name (client_cert ), subject ,
279321 sizeof (subject ));
322+ subject [sizeof (subject ) - 1 ] = '\0' ;
323+ if (subject [0 ] && (strlen (subject ) < MAX_STRING_LEN )) {
324+ pairadd (& handler -> certs ,
325+ pairmake (cert_attr_names [2 ][lookup ], subject , T_OP_SET ));
326+ }
327+
280328 X509_NAME_oneline (X509_get_issuer_name (ctx -> current_cert ), issuer ,
281329 sizeof (issuer ));
282-
283- subject [sizeof (subject ) - 1 ] = '\0' ;
284330 issuer [sizeof (issuer ) - 1 ] = '\0' ;
331+ if (issuer [0 ] && (strlen (issuer ) < MAX_STRING_LEN )) {
332+ pairadd (& handler -> certs ,
333+ pairmake (cert_attr_names [3 ][lookup ], issuer , T_OP_SET ));
334+ }
285335
286336 /*
287337 * Get the Common Name
288338 */
289339 X509_NAME_get_text_by_NID (X509_get_subject_name (client_cert ),
290340 NID_commonName , common_name , sizeof (common_name ));
291341 common_name [sizeof (common_name ) - 1 ] = '\0' ;
342+ if (common_name [0 ] && (strlen (common_name ) < MAX_STRING_LEN )) {
343+ pairadd (& handler -> certs ,
344+ pairmake (cert_attr_names [4 ][lookup ], common_name , T_OP_SET ));
345+ }
346+
347+ if (!my_ok ) {
348+ const char * p = X509_verify_cert_error_string (err );
349+ radlog (L_ERR ,"--> verify error:num=%d:%s\n" ,err , p );
350+ radius_pairmake (request , & request -> packet -> vps ,
351+ "Module-Failure-Message" , p , T_OP_SET );
352+ return my_ok ;
353+ }
292354
293355 switch (ctx -> error ) {
294356
0 commit comments