Scan media entities as well, not just url entities. This should expand more
[bitlbee.git] / lib / ssl_nss.c
blobd50620d5831e6ec29626d815000105435b5cf74b
1 /********************************************************************\
2 * BitlBee -- An IRC to other IM-networks gateway *
3 * *
4 * Copyright 2002-2005 Wilmer van der Gaast and others *
5 \********************************************************************/
7 /* SSL module - NSS version */
9 /* Copyright 2005 Jelmer Vernooij */
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License with
23 the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
24 if not, write to the Free Software Foundation, Inc., 59 Temple Place,
25 Suite 330, Boston, MA 02111-1307 USA
28 #include "bitlbee.h"
29 #include "proxy.h"
30 #include "ssl_client.h"
31 #include "sock.h"
32 #include <nspr.h>
33 #include <prio.h>
34 #include <sslproto.h>
35 #include <nss.h>
36 #include <pk11pub.h>
37 #include <private/pprio.h>
38 #include <ssl.h>
39 #include <seccomon.h>
40 #include <secerr.h>
41 #include <sslerr.h>
43 int ssl_errno = 0;
45 static gboolean initialized = FALSE;
47 struct scd
49 ssl_input_function func;
50 gpointer data;
51 int fd;
52 PRFileDesc *prfd;
53 gboolean established;
54 gboolean verify;
57 static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
58 static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond );
61 static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver)
63 return SECSuccess;
66 static SECStatus nss_bad_cert (void *arg, PRFileDesc *socket)
68 PRErrorCode err;
70 if(!arg) return SECFailure;
72 *(PRErrorCode *)arg = err = PORT_GetError();
74 switch(err) {
75 case SEC_ERROR_INVALID_AVA:
76 case SEC_ERROR_INVALID_TIME:
77 case SEC_ERROR_BAD_SIGNATURE:
78 case SEC_ERROR_EXPIRED_CERTIFICATE:
79 case SEC_ERROR_UNKNOWN_ISSUER:
80 case SEC_ERROR_UNTRUSTED_CERT:
81 case SEC_ERROR_CERT_VALID:
82 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
83 case SEC_ERROR_CRL_EXPIRED:
84 case SEC_ERROR_CRL_BAD_SIGNATURE:
85 case SEC_ERROR_EXTENSION_VALUE_INVALID:
86 case SEC_ERROR_CA_CERT_INVALID:
87 case SEC_ERROR_CERT_USAGES_INVALID:
88 case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
89 return SECSuccess;
91 default:
92 return SECFailure;
97 void ssl_init( void )
99 PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
100 NSS_NoDB_Init(NULL);
101 NSS_SetDomesticPolicy();
102 initialized = TRUE;
105 void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data )
107 struct scd *conn = g_new0( struct scd, 1 );
109 conn->fd = proxy_connect( host, port, ssl_connected, conn );
110 conn->func = func;
111 conn->data = data;
113 if( conn->fd < 0 )
115 g_free( conn );
116 return( NULL );
119 if( !initialized )
121 ssl_init();
125 return( conn );
128 static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond )
130 struct scd *conn = data;
132 return ssl_connected( conn, conn->fd, B_EV_IO_WRITE );
135 void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data )
137 struct scd *conn = g_new0( struct scd, 1 );
139 conn->fd = fd;
140 conn->func = func;
141 conn->data = data;
142 conn->verify = verify && global.conf->cafile;
144 /* This function should be called via a (short) timeout instead of
145 directly from here, because these SSL calls are *supposed* to be
146 *completely* asynchronous and not ready yet when this function
147 (or *_connect, for examle) returns. Also, errors are reported via
148 the callback function, not via this function's return value.
150 In short, doing things like this makes the rest of the code a lot
151 simpler. */
153 b_timeout_add( 1, ssl_starttls_real, conn );
155 return conn;
158 static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
160 struct scd *conn = data;
162 /* Right now we don't have any verification functionality for NSS. */
164 if( conn->verify )
166 conn->func( conn->data, 1, NULL, cond );
167 if( source >= 0 ) closesocket( source );
168 g_free( conn );
170 return FALSE;
173 if( source == -1 )
174 goto ssl_connected_failure;
176 /* Until we find out how to handle non-blocking I/O with NSS... */
177 sock_make_blocking( conn->fd );
179 conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source));
180 SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE);
181 SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
182 SSL_BadCertHook(conn->prfd, (SSLBadCertHandler)nss_bad_cert, NULL);
183 SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate)nss_auth_cert, (void *)CERT_GetDefaultCertDB());
184 SSL_ResetHandshake(conn->prfd, PR_FALSE);
186 if (SSL_ForceHandshake(conn->prfd)) {
187 goto ssl_connected_failure;
191 conn->established = TRUE;
192 conn->func( conn->data, 0, conn, cond );
193 return FALSE;
195 ssl_connected_failure:
197 conn->func( conn->data, 0, NULL, cond );
199 PR_Close( conn -> prfd );
200 if( source >= 0 ) closesocket( source );
201 g_free( conn );
203 return FALSE;
206 int ssl_read( void *conn, char *buf, int len )
208 if( !((struct scd*)conn)->established )
209 return( 0 );
211 return( PR_Read( ((struct scd*)conn)->prfd, buf, len ) );
214 int ssl_write( void *conn, const char *buf, int len )
216 if( !((struct scd*)conn)->established )
217 return( 0 );
219 return( PR_Write ( ((struct scd*)conn)->prfd, buf, len ) );
222 int ssl_pending( void *conn )
224 struct scd *c = (struct scd *) conn;
226 if( c == NULL ) {
227 return 0;
230 return ( c->established && SSL_DataPending( c->prfd ) > 0 );
233 void ssl_disconnect( void *conn_ )
235 struct scd *conn = conn_;
237 PR_Close( conn->prfd );
238 closesocket( conn->fd );
240 g_free( conn );
243 int ssl_getfd( void *conn )
245 return( ((struct scd*)conn)->fd );
248 b_input_condition ssl_getdirection( void *conn )
250 /* Just in case someone calls us, let's return the most likely case: */
251 return B_EV_IO_READ;
254 char *ssl_verify_strerror( int code )
256 return g_strdup( "SSL certificate verification not supported by BitlBee NSS code." );