/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * \********************************************************************/ /* SSL module - SSPI backend */ /* Copyright (C) 2005 Jelmer Vernooij */ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License with the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ssl_client.h" #include #define SECURITY_WIN32 #include #include #include #include "sock.h" static gboolean initialized = FALSE; int ssl_errno; struct scd { int fd; ssl_input_function func; gpointer data; gboolean established; CredHandle cred; /* SSL credentials */ CtxtHandle context; /* SSL context */ SecPkgContext_StreamSizes sizes; char *host; char *pending_raw_data; gsize pending_raw_data_len; char *pending_data; gsize pending_data_len; }; static void ssl_connected(gpointer, gint, GaimInputCondition); void sspi_global_init(void) { /* FIXME */ } void sspi_global_deinit(void) { /* FIXME */ } void *ssl_connect(char *host, int port, ssl_input_function func, gpointer data) { struct scd *conn = g_new0(struct scd, 1); conn->fd = proxy_connect(host, port, ssl_connected, conn); sock_make_nonblocking(conn->fd); conn->func = func; conn->data = data; conn->host = g_strdup(host); if (conn->fd < 0) { g_free(conn); return NULL; } if (!initialized) { sspi_global_init(); initialized = TRUE; atexit(sspi_global_deinit); } return conn; } static void ssl_connected(gpointer _conn, gint fd, GaimInputCondition cond) { struct scd *conn = _conn; SCHANNEL_CRED ssl_cred; TimeStamp timestamp; SecBuffer ibuf[2],obuf[1]; SecBufferDesc ibufs,obufs; ULONG req = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR | ISC_REQ_MANUAL_CRED_VALIDATION; ULONG a; gsize size = 0; gchar *data = NULL; memset(&ssl_cred, 0, sizeof(SCHANNEL_CRED)); ssl_cred.dwVersion = SCHANNEL_CRED_VERSION; ssl_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; SECURITY_STATUS st = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &ssl_cred, NULL, NULL, &conn->cred, ×tamp); if (st != SEC_E_OK) { conn->func(conn->data, NULL, cond); return; } do { /* initialize buffers */ ibuf[0].cbBuffer = size; ibuf[0].pvBuffer = data; ibuf[1].cbBuffer = 0; ibuf[1].pvBuffer = NULL; obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NULL; ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN; ibuf[1].BufferType = SECBUFFER_EMPTY; /* initialize buffer descriptors */ ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION; ibufs.cBuffers = 2; obufs.cBuffers = 1; ibufs.pBuffers = ibuf; obufs.pBuffers = obuf; st = InitializeSecurityContext(&conn->cred, size?&conn->context:NULL, conn->host, req, 0, SECURITY_NETWORK_DREP, size?&ibufs:NULL, 0, &conn->context, &obufs, &a, ×tamp); if (obuf[0].pvBuffer