1/*
2 * Copyright (C) 1997-2000 Sensus Consulting Ltd.
3 * Matt Newman <matt@sensus.org>
4 *
5 * $Header: /cvsroot/tls/tls/tlsX509.c,v 1.5 2004/06/29 10:58:08 patthoyts Exp $
6 */
7#include "tlsInt.h"
8
9/*
10 *  Ensure these are not macros - known to be defined on Win32
11 */
12#ifdef min
13#undef min
14#endif
15
16#ifdef max
17#undef max
18#endif
19
20static int min(int a, int b)
21{
22    return (a < b) ? a : b;
23}
24
25static int max(int a, int b)
26{
27    return (a > b) ? a : b;
28}
29
30/*
31 * ASN1_UTCTIME_tostr --
32 */
33static char *
34ASN1_UTCTIME_tostr(ASN1_UTCTIME *tm)
35{
36    static char bp[128];
37    char *v;
38    int gmt=0;
39    static char *mon[12]={
40        "Jan","Feb","Mar","Apr","May","Jun",
41        "Jul","Aug","Sep","Oct","Nov","Dec"};
42    int i;
43    int y=0,M=0,d=0,h=0,m=0,s=0;
44
45    i=tm->length;
46    v=(char *)tm->data;
47
48    if (i < 10) goto err;
49    if (v[i-1] == 'Z') gmt=1;
50    for (i=0; i<10; i++)
51        if ((v[i] > '9') || (v[i] < '0')) goto err;
52    y= (v[0]-'0')*10+(v[1]-'0');
53    if (y < 70) y+=100;
54    M= (v[2]-'0')*10+(v[3]-'0');
55    if ((M > 12) || (M < 1)) goto err;
56    d= (v[4]-'0')*10+(v[5]-'0');
57    h= (v[6]-'0')*10+(v[7]-'0');
58    m=  (v[8]-'0')*10+(v[9]-'0');
59    if (	(v[10] >= '0') && (v[10] <= '9') &&
60		(v[11] >= '0') && (v[11] <= '9'))
61        s=  (v[10]-'0')*10+(v[11]-'0');
62
63    sprintf(bp,"%s %2d %02d:%02d:%02d %d%s",
64                   mon[M-1],d,h,m,s,y+1900,(gmt)?" GMT":"");
65    return bp;
66 err:
67    return "Bad time value";
68}
69
70/*
71 *------------------------------------------------------*
72 *
73 *	Tls_NewX509Obj --
74 *
75 *	------------------------------------------------*
76 *	Converts a X509 certificate into a Tcl_Obj
77 *	------------------------------------------------*
78 *
79 *	Sideeffects:
80 *		None
81 *
82 *	Result:
83 *		A Tcl List Object representing the provided
84 *		X509 certificate.
85 *
86 *------------------------------------------------------*
87 */
88
89Tcl_Obj*
90Tls_NewX509Obj( interp, cert)
91    Tcl_Interp *interp;
92    X509 *cert;
93{
94    Tcl_Obj *certPtr = Tcl_NewListObj( 0, NULL);
95    BIO *bio;
96    int n;
97    unsigned long flags;
98    char subject[BUFSIZ];
99    char issuer[BUFSIZ];
100    char serial[BUFSIZ];
101    char notBefore[BUFSIZ];
102    char notAfter[BUFSIZ];
103#ifndef NO_SSL_SHA
104    int shai;
105    char sha_hash[SHA_DIGEST_LENGTH*2];
106    const char *shachars="0123456789ABCDEF";
107#endif
108
109    if ((bio = BIO_new(BIO_s_mem())) == NULL) {
110	subject[0] = 0;
111	issuer[0]  = 0;
112	serial[0]  = 0;
113    } else {
114	flags = XN_FLAG_RFC2253 | ASN1_STRFLGS_UTF8_CONVERT;
115	flags &= ~ASN1_STRFLGS_ESC_MSB;
116
117	X509_NAME_print_ex(bio, X509_get_subject_name(cert), 0, flags);
118	n = BIO_read(bio, subject, min(BIO_pending(bio), BUFSIZ - 1));
119	n = max(n, 0);
120	subject[n] = 0;
121	BIO_flush(bio);
122
123	X509_NAME_print_ex(bio, X509_get_issuer_name(cert), 0, flags);
124	n = BIO_read(bio, issuer, min(BIO_pending(bio), BUFSIZ - 1));
125	n = max(n, 0);
126	issuer[n] = 0;
127	BIO_flush(bio);
128
129	i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
130	n = BIO_read(bio, serial, min(BIO_pending(bio), BUFSIZ - 1));
131	n = max(n, 0);
132	serial[n] = 0;
133	BIO_flush(bio);
134
135	BIO_free(bio);
136    }
137
138    strcpy( notBefore, ASN1_UTCTIME_tostr( X509_get_notBefore(cert) ));
139    strcpy( notAfter, ASN1_UTCTIME_tostr( X509_get_notAfter(cert) ));
140
141#ifndef NO_SSL_SHA
142    for (shai=0;shai<SHA_DIGEST_LENGTH;shai++)
143    {
144        sha_hash[shai * 2]=shachars[(cert->sha1_hash[shai] & 0xF0) >> 4];
145        sha_hash[shai * 2 + 1]=shachars[(cert->sha1_hash[shai] & 0x0F)];
146    }
147    Tcl_ListObjAppendElement( interp, certPtr,
148	    Tcl_NewStringObj( "sha1_hash", -1) );
149    Tcl_ListObjAppendElement( interp, certPtr,
150	    Tcl_NewStringObj( sha_hash, SHA_DIGEST_LENGTH*2) );
151
152#endif
153    Tcl_ListObjAppendElement( interp, certPtr,
154	    Tcl_NewStringObj( "subject", -1) );
155    Tcl_ListObjAppendElement( interp, certPtr,
156	    Tcl_NewStringObj( subject, -1) );
157
158    Tcl_ListObjAppendElement( interp, certPtr,
159	    Tcl_NewStringObj( "issuer", -1) );
160    Tcl_ListObjAppendElement( interp, certPtr,
161	    Tcl_NewStringObj( issuer, -1) );
162
163    Tcl_ListObjAppendElement( interp, certPtr,
164	    Tcl_NewStringObj( "notBefore", -1) );
165    Tcl_ListObjAppendElement( interp, certPtr,
166	    Tcl_NewStringObj( notBefore, -1) );
167
168    Tcl_ListObjAppendElement( interp, certPtr,
169	    Tcl_NewStringObj( "notAfter", -1) );
170    Tcl_ListObjAppendElement( interp, certPtr,
171	    Tcl_NewStringObj( notAfter, -1) );
172
173    Tcl_ListObjAppendElement( interp, certPtr,
174	    Tcl_NewStringObj( "serial", -1) );
175    Tcl_ListObjAppendElement( interp, certPtr,
176	    Tcl_NewStringObj( serial, -1) );
177
178    return certPtr;
179}
180