1/*
2	sslclient.c
3
4	Example SSL-secure client.
5
6	SSL-enabled services use the gSOAP SSL interface. See sslclient.c and
7	sslserver.c for example code with instructions and the gSOAP
8	documentation more details.
9
10--------------------------------------------------------------------------------
11gSOAP XML Web services tools
12Copyright (C) 2001-2008, Robert van Engelen, Genivia, Inc. All Rights Reserved.
13This software is released under one of the following two licenses:
14GPL or Genivia's license for commercial use.
15--------------------------------------------------------------------------------
16GPL license.
17
18This program is free software; you can redistribute it and/or modify it under
19the terms of the GNU General Public License as published by the Free Software
20Foundation; either version 2 of the License, or (at your option) any later
21version.
22
23This program is distributed in the hope that it will be useful, but WITHOUT ANY
24WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
25PARTICULAR PURPOSE. See the GNU General Public License for more details.
26
27You should have received a copy of the GNU General Public License along with
28this program; if not, write to the Free Software Foundation, Inc., 59 Temple
29Place, Suite 330, Boston, MA 02111-1307 USA
30
31Author contact information:
32engelen@genivia.com / engelen@acm.org
33--------------------------------------------------------------------------------
34A commercial use license is available from Genivia, Inc., contact@genivia.com
35--------------------------------------------------------------------------------
36*/
37
38#include "soapH.h"
39#include "ssl.nsmap"
40
41#include <unistd.h>		/* defines _POSIX_THREADS if pthreads are available */
42#ifdef _POSIX_THREADS
43#include <pthread.h>
44#endif
45
46#include <signal.h>		/* defines SIGPIPE */
47
48const char server[] = "https://localhost:18081";
49
50int CRYPTO_thread_setup();
51void CRYPTO_thread_cleanup();
52void sigpipe_handle(int);
53
54int main()
55{ struct soap soap;
56  double a, b, result;
57  /* Init OpenSSL */
58  soap_ssl_init();
59  if (CRYPTO_thread_setup())
60  { fprintf(stderr, "Cannot setup thread mutex\n");
61    exit(1);
62  }
63  a = 10.0;
64  b = 20.0;
65  /* Init gSOAP context */
66  soap_init(&soap);
67  /* The supplied server certificate "server.pem" assumes that the server is
68    running on 'localhost', so clients can only connect from the same host when
69    verifying the server's certificate. Use SOAP_SSL_NO_AUTHENTICATION to omit
70    the authentication of the server and use encryption directly from any site.
71    To verify the certificates of third-party services, they must provide a
72    certificate issued by Verisign or another trusted CA. At the client-side,
73    the capath parameter should point to a directory that contains these
74    trusted (root) certificates or the cafile parameter should refer to one
75    file will all certificates. To help you out, the supplied "cacerts.pem"
76    file contains the certificates issued by various CAs. You should use this
77    file for the cafile parameter instead of "cacert.pem" to connect to trusted
78    servers.  Note that the client may fail to connect if the server's
79    credentials have problems (e.g. expired). Use SOAP_SSL_NO_AUTHENTICATION
80    and set cacert to NULL to encrypt messages if you don't care about the
81    trustworthyness of the server.  Note: setting capath may not work on
82    Windows.
83  */
84  if (soap_ssl_client_context(&soap,
85    SOAP_SSL_DEFAULT | SOAP_SSL_SKIP_HOST_CHECK,	/* use SOAP_SSL_DEFAULT in production code, we don't want the host name checks since these will change from machine to machine */
86    NULL, 		/* keyfile: required only when client must authenticate to server (see SSL docs on how to obtain this file) */
87    NULL, 		/* password to read the keyfile */
88    "cacert.pem",	/* optional cacert file to store trusted certificates, use cacerts.pem for all public certificates issued by common CAs */
89    NULL,		/* optional capath to directory with trusted certificates */
90    NULL		/* if randfile!=NULL: use a file with random data to seed randomness */
91  ))
92  { soap_print_fault(&soap, stderr);
93    exit(1);
94  }
95  if (soap_call_ns__add(&soap, server, "", a, b, &result) == SOAP_OK)
96    fprintf(stdout, "Result: %f + %f = %f\n", a, b, result);
97  else
98    soap_print_fault(&soap, stderr);
99  soap_destroy(&soap); /* C++ */
100  soap_end(&soap);
101  soap_done(&soap);
102  CRYPTO_thread_cleanup();
103  return 0;
104}
105
106/******************************************************************************\
107 *
108 *	OpenSSL
109 *
110\******************************************************************************/
111
112#ifdef WITH_OPENSSL
113
114#if defined(WIN32)
115# define MUTEX_TYPE		HANDLE
116# define MUTEX_SETUP(x)		(x) = CreateMutex(NULL, FALSE, NULL)
117# define MUTEX_CLEANUP(x)	CloseHandle(x)
118# define MUTEX_LOCK(x)		WaitForSingleObject((x), INFINITE)
119# define MUTEX_UNLOCK(x)	ReleaseMutex(x)
120# define THREAD_ID		GetCurrentThreadId()
121#elif defined(_POSIX_THREADS)
122# define MUTEX_TYPE		pthread_mutex_t
123# define MUTEX_SETUP(x)		pthread_mutex_init(&(x), NULL)
124# define MUTEX_CLEANUP(x)	pthread_mutex_destroy(&(x))
125# define MUTEX_LOCK(x)		pthread_mutex_lock(&(x))
126# define MUTEX_UNLOCK(x)	pthread_mutex_unlock(&(x))
127# define THREAD_ID		pthread_self()
128#else
129# error "You must define mutex operations appropriate for your platform"
130# error	"See OpenSSL /threads/th-lock.c on how to implement mutex on your platform"
131#endif
132
133struct CRYPTO_dynlock_value
134{ MUTEX_TYPE mutex;
135};
136
137static MUTEX_TYPE *mutex_buf;
138
139static struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line)
140{ struct CRYPTO_dynlock_value *value;
141  value = (struct CRYPTO_dynlock_value*)malloc(sizeof(struct CRYPTO_dynlock_value));
142  if (value)
143    MUTEX_SETUP(value->mutex);
144  return value;
145}
146
147static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
148{ if (mode & CRYPTO_LOCK)
149    MUTEX_LOCK(l->mutex);
150  else
151    MUTEX_UNLOCK(l->mutex);
152}
153
154static void dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char *file, int line)
155{ MUTEX_CLEANUP(l->mutex);
156  free(l);
157}
158
159void locking_function(int mode, int n, const char *file, int line)
160{ if (mode & CRYPTO_LOCK)
161    MUTEX_LOCK(mutex_buf[n]);
162  else
163    MUTEX_UNLOCK(mutex_buf[n]);
164}
165
166unsigned long id_function()
167{ return (unsigned long)THREAD_ID;
168}
169
170int CRYPTO_thread_setup()
171{ int i;
172  mutex_buf = (MUTEX_TYPE*)malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
173  if (!mutex_buf)
174    return SOAP_EOM;
175  for (i = 0; i < CRYPTO_num_locks(); i++)
176    MUTEX_SETUP(mutex_buf[i]);
177  CRYPTO_set_id_callback(id_function);
178  CRYPTO_set_locking_callback(locking_function);
179  CRYPTO_set_dynlock_create_callback(dyn_create_function);
180  CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
181  CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
182  return SOAP_OK;
183}
184
185void CRYPTO_thread_cleanup()
186{ int i;
187  if (!mutex_buf)
188    return;
189  CRYPTO_set_id_callback(NULL);
190  CRYPTO_set_locking_callback(NULL);
191  CRYPTO_set_dynlock_create_callback(NULL);
192  CRYPTO_set_dynlock_lock_callback(NULL);
193  CRYPTO_set_dynlock_destroy_callback(NULL);
194  for (i = 0; i < CRYPTO_num_locks(); i++)
195    MUTEX_CLEANUP(mutex_buf[i]);
196  free(mutex_buf);
197  mutex_buf = NULL;
198}
199
200#endif
201
202/******************************************************************************\
203 *
204 *	SIGPIPE
205 *
206\******************************************************************************/
207
208void sigpipe_handle(int x) { }
209
210